<?php
/* Copyright (C) 2026 Alles Watt lauft
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 */

/**
 * Class AnlageFile
 * Manages file attachments for installation elements
 */
class AnlageFile extends CommonObject
{
	public $element = 'anlagefile';
	public $table_element = 'kundenkarte_anlage_files';

	public $fk_anlage;
	public $filename;
	public $filepath;
	public $filesize;
	public $mimetype;
	public $file_type;
	public $label;
	public $description;
	public $is_cover;
	public $is_pinned;
	public $position;
	public $share;

	public $date_creation;
	public $fk_user_creat;
	public $fk_user_modif;

	/**
	 * Constructor
	 *
	 * @param DoliDB $db Database handler
	 */
	public function __construct($db)
	{
		$this->db = $db;
	}

	/**
	 * Create object in database
	 *
	 * @param User $user User that creates
	 * @return int Return integer <0 if KO, Id of created object if OK
	 */
	public function create($user)
	{
		global $conf;

		$error = 0;
		$now = dol_now();

		if (empty($this->fk_anlage) || empty($this->filename) || empty($this->filepath)) {
			$this->error = 'ErrorMissingParameters';
			return -1;
		}

		// Determine file type
		if (empty($this->file_type)) {
			$this->file_type = $this->determineFileType($this->mimetype, $this->filename);
		}

		$this->db->begin();

		$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
		$sql .= "entity, fk_anlage, filename, filepath, filesize, mimetype,";
		$sql .= " file_type, label, description, is_cover, is_pinned, position, share,";
		$sql .= " date_creation, fk_user_creat";
		$sql .= ") VALUES (";
		$sql .= ((int) $conf->entity);
		$sql .= ", ".((int) $this->fk_anlage);
		$sql .= ", '".$this->db->escape($this->filename)."'";
		$sql .= ", '".$this->db->escape($this->filepath)."'";
		$sql .= ", ".((int) $this->filesize);
		$sql .= ", ".($this->mimetype ? "'".$this->db->escape($this->mimetype)."'" : "NULL");
		$sql .= ", '".$this->db->escape($this->file_type)."'";
		$sql .= ", ".($this->label ? "'".$this->db->escape($this->label)."'" : "NULL");
		$sql .= ", ".($this->description ? "'".$this->db->escape($this->description)."'" : "NULL");
		$sql .= ", ".((int) $this->is_cover);
		$sql .= ", ".((int) $this->is_pinned);
		$sql .= ", ".((int) $this->position);
		$sql .= ", ".($this->share ? "'".$this->db->escape($this->share)."'" : "NULL");
		$sql .= ", '".$this->db->idate($now)."'";
		$sql .= ", ".((int) $user->id);
		$sql .= ")";

		$resql = $this->db->query($sql);
		if (!$resql) {
			$error++;
			$this->errors[] = "Error ".$this->db->lasterror();
		}

		if (!$error) {
			$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
		}

		if ($error) {
			$this->db->rollback();
			return -1 * $error;
		} else {
			$this->db->commit();
			return $this->id;
		}
	}

	/**
	 * Load object from database
	 *
	 * @param int $id ID of record
	 * @return int Return integer <0 if KO, 0 if not found, >0 if OK
	 */
	public function fetch($id)
	{
		global $conf;

		$sql = "SELECT * FROM ".MAIN_DB_PREFIX.$this->table_element;
		$sql .= " WHERE rowid = ".((int) $id);
		$sql .= " AND entity = ".((int) $conf->entity);

		$resql = $this->db->query($sql);
		if ($resql) {
			if ($this->db->num_rows($resql)) {
				$obj = $this->db->fetch_object($resql);

				$this->id = $obj->rowid;
				$this->entity = $obj->entity;
				$this->fk_anlage = $obj->fk_anlage;
				$this->filename = $obj->filename;
				$this->filepath = $obj->filepath;
				$this->filesize = $obj->filesize;
				$this->mimetype = $obj->mimetype;
				$this->file_type = $obj->file_type;
				$this->label = $obj->label;
				$this->description = $obj->description;
				$this->is_cover = $obj->is_cover;
				$this->is_pinned = $obj->is_pinned;
				$this->position = $obj->position;
				$this->share = $obj->share;
				$this->date_creation = $this->db->jdate($obj->date_creation);
				$this->fk_user_creat = $obj->fk_user_creat;
				$this->fk_user_modif = $obj->fk_user_modif;

				$this->db->free($resql);
				return 1;
			} else {
				$this->db->free($resql);
				return 0;
			}
		} else {
			$this->error = $this->db->lasterror();
			return -1;
		}
	}

	/**
	 * Delete object in database and file from disk
	 *
	 * @param User $user User that deletes
	 * @return int Return integer <0 if KO, >0 if OK
	 */
	public function delete($user)
	{
		global $conf;

		$error = 0;

		// Delete physical file (use clean filepath)
		$fullpath = $this->getFullPath();
		if (file_exists($fullpath)) {
			dol_delete_file($fullpath);

			// Delete thumbnail if exists
			$thumbpath = dirname($fullpath).'/thumbs/'.pathinfo($this->filename, PATHINFO_FILENAME).'_small.'.pathinfo($this->filename, PATHINFO_EXTENSION);
			if (file_exists($thumbpath)) {
				dol_delete_file($thumbpath);
			}
		}

		$this->db->begin();

		$sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element." WHERE rowid = ".((int) $this->id);
		$resql = $this->db->query($sql);
		if (!$resql) {
			$error++;
			$this->errors[] = "Error ".$this->db->lasterror();
		}

		if ($error) {
			$this->db->rollback();
			return -1 * $error;
		} else {
			$this->db->commit();
			return 1;
		}
	}

	/**
	 * Fetch all files for an installation element
	 *
	 * @param int $anlageId Installation element ID
	 * @param string $fileType Filter by file type (image, pdf, document, other)
	 * @return array Array of AnlageFile objects
	 */
	public function fetchAllByAnlage($anlageId, $fileType = '')
	{
		global $conf;

		$results = array();

		$sql = "SELECT * FROM ".MAIN_DB_PREFIX.$this->table_element;
		$sql .= " WHERE fk_anlage = ".((int) $anlageId);
		$sql .= " AND entity = ".((int) $conf->entity);
		if ($fileType) {
			$sql .= " AND file_type = '".$this->db->escape($fileType)."'";
		}
		$sql .= " ORDER BY is_pinned DESC, is_cover DESC, position ASC, filename ASC";

		$resql = $this->db->query($sql);
		if ($resql) {
			while ($obj = $this->db->fetch_object($resql)) {
				$file = new AnlageFile($this->db);
				$file->id = $obj->rowid;
				$file->fk_anlage = $obj->fk_anlage;
				$file->filename = $obj->filename;
				$file->filepath = $obj->filepath;
				$file->filesize = $obj->filesize;
				$file->mimetype = $obj->mimetype;
				$file->file_type = $obj->file_type;
				$file->label = $obj->label;
				$file->description = $obj->description;
				$file->is_cover = $obj->is_cover;
				$file->is_pinned = $obj->is_pinned;
				$file->position = $obj->position;
				$file->share = $obj->share;
				$file->date_creation = $this->db->jdate($obj->date_creation);

				$results[] = $file;
			}
			$this->db->free($resql);
		}

		return $results;
	}

	/**
	 * Determine file type from mimetype and filename
	 *
	 * @param string $mimetype MIME type
	 * @param string $filename Filename
	 * @return string File type (image, pdf, document, other)
	 */
	public function determineFileType($mimetype, $filename)
	{
		$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));

		if (in_array($ext, array('jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp')) || strpos($mimetype, 'image/') === 0) {
			return 'image';
		}
		if ($ext == 'pdf' || $mimetype == 'application/pdf') {
			return 'pdf';
		}
		if (in_array($ext, array('doc', 'docx', 'xls', 'xlsx', 'odt', 'ods', 'txt', 'rtf'))) {
			return 'document';
		}
		if (in_array($ext, array('zip', 'rar', '7z', 'tar', 'gz', 'tgz'))) {
			return 'archive';
		}

		return 'other';
	}

	/**
	 * Get full file path
	 *
	 * @return string
	 */
	public function getFullPath()
	{
		global $conf;
		return $conf->kundenkarte->dir_output.'/'.$this->getCleanFilepath();
	}

	/**
	 * Get URL to view/download the file
	 *
	 * @param bool $forceDownload If true, force download instead of inline display
	 * @return string
	 */
	public function getUrl($forceDownload = false)
	{
		// Sanitize filepath - ensure it's relative, not absolute
		$filepath = $this->getCleanFilepath();
		$url = DOL_URL_ROOT.'/document.php?modulepart=kundenkarte&file='.urlencode($filepath);

		// Add attachment=0 for inline display (especially for PDFs)
		// If forceDownload is true, don't add this parameter (default Dolibarr behavior is download)
		if (!$forceDownload) {
			$url .= '&attachment=0';
		}

		return $url;
	}

	/**
	 * Get clean relative filepath (fixes bad data)
	 *
	 * @return string Clean relative filepath
	 */
	public function getCleanFilepath()
	{
		$filepath = $this->filepath;

		// If filepath contains "anlagen/" extract from there
		if (strpos($filepath, 'anlagen/') !== false) {
			$filepath = substr($filepath, strpos($filepath, 'anlagen/'));
		}
		// If it's still an absolute path (starts with / or file:// or Windows drive), just use filename
		elseif (preg_match('/^(\/|file:\/\/|[A-Za-z]:)/', $filepath)) {
			// Try to get just the filename and rebuild proper path
			$filename = basename($filepath);
			// Use fk_anlage to build correct path if available
			if ($this->fk_anlage > 0) {
				global $db;
				$sql = "SELECT fk_soc FROM ".MAIN_DB_PREFIX."kundenkarte_anlage WHERE rowid = ".((int) $this->fk_anlage);
				$resql = $db->query($sql);
				if ($resql && $db->num_rows($resql)) {
					$obj = $db->fetch_object($resql);
					$filepath = 'anlagen/'.$obj->fk_soc.'/'.$this->fk_anlage.'/'.$filename;
				}
			}
		}

		return $filepath;
	}

	/**
	 * Get thumbnail URL for images
	 *
	 * @return string
	 */
	public function getThumbUrl()
	{
		if ($this->file_type != 'image') {
			return '';
		}

		$filepath = $this->getCleanFilepath();
		$dir = dirname($filepath);
		$filename = pathinfo($this->filename, PATHINFO_FILENAME);
		$ext = pathinfo($this->filename, PATHINFO_EXTENSION);

		$thumbpath = $dir.'/thumbs/'.$filename.'_small.'.$ext;

		// Use attachment=0 for inline display
		return DOL_URL_ROOT.'/document.php?modulepart=kundenkarte&file='.urlencode($thumbpath).'&attachment=0';
	}

	/**
	 * Set this file as cover image
	 *
	 * @param User $user User making the change
	 * @return int <0 if KO, >0 if OK
	 */
	public function setAsCover($user)
	{
		$this->db->begin();

		// Unset other covers for this anlage
		$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET is_cover = 0";
		$sql .= " WHERE fk_anlage = ".((int) $this->fk_anlage);
		$this->db->query($sql);

		// Set this as cover
		$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET is_cover = 1, fk_user_modif = ".((int) $user->id);
		$sql .= " WHERE rowid = ".((int) $this->id);
		$resql = $this->db->query($sql);

		if ($resql) {
			$this->is_cover = 1;
			$this->db->commit();
			return 1;
		} else {
			$this->db->rollback();
			return -1;
		}
	}

	/**
	 * Toggle pinned status of file
	 *
	 * @param User $user User making the change
	 * @return int <0 if KO, >0 if OK
	 */
	public function togglePin($user)
	{
		$newStatus = $this->is_pinned ? 0 : 1;

		$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
		$sql .= " SET is_pinned = ".((int) $newStatus);
		$sql .= ", fk_user_modif = ".((int) $user->id);
		$sql .= " WHERE rowid = ".((int) $this->id);

		$resql = $this->db->query($sql);
		if ($resql) {
			$this->is_pinned = $newStatus;
			return 1;
		}
		return -1;
	}

	/**
	 * Generate thumbnail for image
	 *
	 * @return bool
	 */
	public function generateThumbnail()
	{
		global $conf;

		if ($this->file_type != 'image') {
			return false;
		}

		require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';

		$fullpath = $this->getFullPath();
		if (!file_exists($fullpath)) {
			return false;
		}

		$thumbdir = dirname($fullpath).'/thumbs';
		if (!is_dir($thumbdir)) {
			dol_mkdir($thumbdir);
		}

		// Generate small thumbnail
		$result = vignette($fullpath, 200, 160, '_small', 80, 'thumbs');

		return ($result !== false);
	}
}
