<?php
/**
 * Project File Model
 *
 * @package Freelance_Studio
 */

if (!defined('ABSPATH')) {
    exit;
}

class FS_Project_File {

    /**
     * File categories
     */
    const CATEGORY_CONTRACT = 'contract';
    const CATEGORY_DELIVERABLE = 'deliverable';
    const CATEGORY_REFERENCE = 'reference';
    const CATEGORY_CLIENT_UPLOAD = 'client_upload';
    const CATEGORY_GENERAL = 'general';

    /**
     * Get table name
     */
    public static function get_table_name() {
        global $wpdb;
        return $wpdb->prefix . 'fs_project_files';
    }

    /**
     * Get all categories
     */
    public static function get_categories() {
        return array(
            self::CATEGORY_CONTRACT => __('Contracts', 'freelance-studio'),
            self::CATEGORY_DELIVERABLE => __('Deliverables', 'freelance-studio'),
            self::CATEGORY_REFERENCE => __('Reference Materials', 'freelance-studio'),
            self::CATEGORY_CLIENT_UPLOAD => __('Client Uploads', 'freelance-studio'),
            self::CATEGORY_GENERAL => __('General', 'freelance-studio'),
        );
    }

    /**
     * Get a single file by ID
     */
    public static function get($id) {
        global $wpdb;
        $table = self::get_table_name();
        
        return $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $table WHERE id = %d",
            $id
        ));
    }

    /**
     * Get file by attachment ID and project ID
     */
    public static function get_by_attachment($attachment_id, $project_id) {
        global $wpdb;
        $table = self::get_table_name();
        
        return $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $table WHERE attachment_id = %d AND project_id = %d",
            $attachment_id,
            $project_id
        ));
    }

    /**
     * Get files for a project
     */
    public static function get_by_project($project_id, $args = array()) {
        global $wpdb;
        $table = self::get_table_name();
        
        $defaults = array(
            'category' => null,
            'shared_with_client' => null,
            'orderby' => 'created_at',
            'order' => 'DESC',
        );
        $args = wp_parse_args($args, $defaults);
        
        $where = array('project_id = %d');
        $params = array($project_id);
        
        if ($args['category']) {
            $where[] = 'category = %s';
            $params[] = $args['category'];
        }
        
        if ($args['shared_with_client'] !== null) {
            $where[] = 'shared_with_client = %d';
            $params[] = $args['shared_with_client'] ? 1 : 0;
        }
        
        $where_sql = implode(' AND ', $where);
        $orderby = sanitize_sql_orderby($args['orderby'] . ' ' . $args['order']) ?: 'created_at DESC';
        
        $sql = "SELECT * FROM $table WHERE $where_sql ORDER BY $orderby";
        
        return $wpdb->get_results($wpdb->prepare($sql, ...$params)); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.NotPrepared
    }

    /**
     * Get files shared with client for a project
     */
    public static function get_shared_files($project_id) {
        return self::get_by_project($project_id, array('shared_with_client' => true));
    }

    /**
     * Create a new project file record
     */
    public static function create($data) {
        global $wpdb;
        $table = self::get_table_name();
        
        $defaults = array(
            'project_id' => 0,
            'attachment_id' => 0,
            'category' => self::CATEGORY_GENERAL,
            'uploaded_by' => get_current_user_id(),
            'uploaded_by_client' => 0,
            'shared_with_client' => 0,
            'notes' => '',
            'created_at' => current_time('mysql'),
        );
        
        $data = wp_parse_args($data, $defaults);
        
        $result = $wpdb->insert($table, $data);
        
        if ($result === false) {
            return false;
        }
        
        return $wpdb->insert_id;
    }

    /**
     * Update a project file record
     */
    public static function update($id, $data) {
        global $wpdb;
        $table = self::get_table_name();
        
        $data['updated_at'] = current_time('mysql');
        
        return $wpdb->update($table, $data, array('id' => $id));
    }

    /**
     * Delete a project file (and optionally the attachment)
     */
    public static function delete($id, $delete_attachment = true) {
        global $wpdb;
        $table = self::get_table_name();
        
        $file = self::get($id);
        if (!$file) {
            return false;
        }
        
        // Delete the WordPress attachment if requested
        if ($delete_attachment && $file->attachment_id) {
            wp_delete_attachment($file->attachment_id, true);
        }
        
        return $wpdb->delete($table, array('id' => $id));
    }

    /**
     * Get file info with attachment details
     */
    public static function get_with_details($id) {
        $file = self::get($id);
        if (!$file) {
            return null;
        }
        
        return self::enrich_file($file);
    }

    /**
     * Enrich file record with attachment details
     */
    public static function enrich_file($file) {
        if (!$file) {
            return $file;
        }
        
        // Set defaults first
        $file->filename = __('Unknown file', 'freelance-studio');
        $file->url = '';
        $file->filesize = 0;
        $file->filesize_formatted = '0 B';
        $file->mime_type = '';
        $file->icon = 'dashicons-media-default';
        $file->is_image = false;
        $file->uploader_name = __('Unknown', 'freelance-studio');
        $file->uploaded_by_type = 'unknown';
        
        // If no attachment_id, return with defaults
        if (empty($file->attachment_id)) {
            return $file;
        }
        
        $attachment = get_post($file->attachment_id);
        if (!$attachment) {
            // Attachment was deleted - keep defaults
            $file->filename = __('File not found', 'freelance-studio');
            return $file;
        }
        
        $attached_file = get_attached_file($file->attachment_id);
        $file->filename = $attached_file ? basename($attached_file) : $attachment->post_title;
        $file->url = wp_get_attachment_url($file->attachment_id);
        
        // Get filesize - handle case where file doesn't exist on disk
        if ($attached_file && file_exists($attached_file)) {
            $file->filesize = filesize($attached_file);
            $file->filesize_formatted = size_format($file->filesize);
        }
        
        $file->mime_type = get_post_mime_type($file->attachment_id);
        $file->icon = self::get_file_icon($file->mime_type);
        $file->is_image = wp_attachment_is_image($file->attachment_id);
        
        if ($file->is_image) {
            $file->thumbnail = wp_get_attachment_image_url($file->attachment_id, 'thumbnail');
        }
        
        // Get uploader info
        if (!empty($file->uploaded_by)) {
            $user = get_user_by('id', $file->uploaded_by);
            $file->uploader_name = $user ? $user->display_name : __('Unknown', 'freelance-studio');
            $file->uploaded_by_type = 'user';
        } elseif (!empty($file->uploaded_by_client)) {
            $file->uploader_name = __('Client', 'freelance-studio');
            $file->uploaded_by_type = 'client';
        }
        
        return $file;
    }

    /**
     * Get dashicon class for file type
     */
    public static function get_file_icon($mime_type) {
        $icons = array(
            'image' => 'dashicons-format-image',
            'video' => 'dashicons-video-alt3',
            'audio' => 'dashicons-format-audio',
            'application/pdf' => 'dashicons-pdf',
            'application/msword' => 'dashicons-media-document',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'dashicons-media-document',
            'application/vnd.ms-excel' => 'dashicons-media-spreadsheet',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'dashicons-media-spreadsheet',
            'application/vnd.ms-powerpoint' => 'dashicons-media-interactive',
            'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'dashicons-media-interactive',
            'application/zip' => 'dashicons-media-archive',
            'application/x-rar-compressed' => 'dashicons-media-archive',
            'text/plain' => 'dashicons-media-text',
            'text/html' => 'dashicons-media-code',
            'text/css' => 'dashicons-media-code',
            'application/javascript' => 'dashicons-media-code',
            'application/json' => 'dashicons-media-code',
        );
        
        // Check for exact match first
        if (isset($icons[$mime_type])) {
            return $icons[$mime_type];
        }
        
        // Check for type prefix
        $type = explode('/', $mime_type)[0];
        if (isset($icons[$type])) {
            return $icons[$type];
        }
        
        return 'dashicons-media-default';
    }

    /**
     * Generate a unique upload token for client uploads
     */
    public static function generate_upload_token($project_id, $expires_days = 7) {
        global $wpdb;
        $table = $wpdb->prefix . 'fs_upload_tokens';
        
        $token = wp_generate_password(32, false);
        $expires_at = gmdate('Y-m-d H:i:s', strtotime("+{$expires_days} days"));
        
        $wpdb->insert($table, array(
            'project_id' => $project_id,
            'token' => $token,
            'expires_at' => $expires_at,
            'created_at' => current_time('mysql'),
        ));
        
        return $token;
    }

    /**
     * Validate upload token
     */
    public static function validate_upload_token($token) {
        global $wpdb;
        $table = $wpdb->prefix . 'fs_upload_tokens';
        
        $record = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $table WHERE token = %s AND expires_at > NOW() AND used_at IS NULL",
            $token
        ));
        
        return $record;
    }

    /**
     * Mark token as used (optional - tokens can be reused until expiry)
     */
    public static function mark_token_used($token) {
        global $wpdb;
        $table = $wpdb->prefix . 'fs_upload_tokens';
        
        return $wpdb->update(
            $table,
            array('used_at' => current_time('mysql')),
            array('token' => $token)
        );
    }

    /**
     * Get project file statistics
     */
    public static function get_project_stats($project_id) {
        global $wpdb;
        $table = self::get_table_name();
        
        $stats = $wpdb->get_row($wpdb->prepare(
            "SELECT 
                COUNT(*) as total_files,
                SUM(CASE WHEN shared_with_client = 1 THEN 1 ELSE 0 END) as shared_files,
                SUM(CASE WHEN uploaded_by_client = 1 THEN 1 ELSE 0 END) as client_uploads
             FROM $table 
             WHERE project_id = %d",
            $project_id
        ));
        
        // Calculate total size
        $files = self::get_by_project($project_id);
        $total_size = 0;
        foreach ($files as $file) {
            $filepath = get_attached_file($file->attachment_id);
            if ($filepath && file_exists($filepath)) {
                $total_size += filesize($filepath);
            }
        }
        
        $stats->total_size = $total_size;
        $stats->total_size_formatted = size_format($total_size);
        
        return $stats;
    }

    /**
     * Get files by category for a project
     */
    public static function get_grouped_by_category($project_id) {
        $files = self::get_by_project($project_id);
        $categories = self::get_categories();
        
        $grouped = array();
        foreach ($categories as $key => $label) {
            $grouped[$key] = array(
                'label' => $label,
                'files' => array(),
            );
        }
        
        foreach ($files as $file) {
            $enriched = self::enrich_file($file);
            $cat = $file->category ?: self::CATEGORY_GENERAL;
            if (isset($grouped[$cat])) {
                $grouped[$cat]['files'][] = $enriched;
            } else {
                $grouped[self::CATEGORY_GENERAL]['files'][] = $enriched;
            }
        }
        
        return $grouped;
    }
}
