<?php

defined('BASEPATH') or exit('No direct script access allowed');

class Content_model extends CI_Model
{
    private $table = 'events';
    private $scheduleTable = 'schedules';
    private $tiles = 'tiles';
    protected $tilesCache = null;


    public function __construct()
    {
        parent::__construct();
        $this->load->library('firebase');
    }




    public function getAllEvents()
    {
        $documents = $this->firebase->getCollection($this->table);
        $events = [];

        foreach ($documents as $id => $data) {
            $events[] = [
                'id'         => $id,
                'name'       => $data['event_name'] ?? 'N/A',
                'start_date' => $data['start_date'] ?? null,
                'created_at' => $data['created_at'] ?? 0,
                'status'     => isset($data['status']) ? ucfirst($data['status']) : 'Draft',
                'users'      => $data['event_members'] ?? [],
            ];
        }

        // 🔽 Sort latest created FIRST
        usort($events, function ($a, $b) {
            return ($b['created_at'] ?? 0) <=> ($a['created_at'] ?? 0);
        });

        return $events;
    }

    public function eventsForDashboard($limit = 5)
    {
        $documents = $this->firebase->getCollection($this->table);
        $events = [];

        foreach ($documents as $id => $data) {
            // Include all events regardless of date
            $startTimestamp = isset($data['start_date']) ? $data['start_date'] / 1000 : 0;

            $events[] = [
                'id' => $id,
                'name' => $data['event_name'] ?? 'N/A',
                'start_date' => isset($data['start_date']) ? date('Y:m:d', $startTimestamp) : 'N/A',
                'start_timestamp' => $startTimestamp, // for sorting (0 if no date)
                'tiles_count' => isset($data['categories']) ? count($data['categories']) : 0,
            ];
        }

        // Sort events by start_timestamp DESCENDING (most recent first)
        // Events with no date (timestamp = 0) will appear at the end
        usort($events, function ($a, $b) {
            return $b['start_timestamp'] <=> $a['start_timestamp']; // DESC order
        });

        // Remove the timestamp from final output
        foreach ($events as &$event) {
            unset($event['start_timestamp']);
        }

        // Return first 5 most recent events
        return array_slice($events, 0, $limit);
    }




    private function getEventTiles($data)
    {
        if (!isset($data['tiles']) || !is_array($data['tiles'])) {
            return [];
        }

        $tileNames = [];
        $tileMapping = [
            'map' => 'Map',
            'rules' => 'Rules',
            'statistics' => 'Statistics',
            'scholarships' => 'Scholarships',
            'dressing_ride_times' => 'Dressing/Ride Times',
            'others' => 'Others',
            'session_packets' => 'Session Packets',
            'programs' => 'Programs',
            'class_sections' => 'Class Sections',
            'patterns' => 'Patterns',
            'admin_chat' => 'Admin Chat'
        ];

        foreach ($data['tiles'] as $key => $tile) {
            if (isset($tile['sections']) && $tile['sections'] > 0) {
                $tileNames[] = $tileMapping[$key] ?? ucfirst(str_replace('_', ' ', $key));
            }
        }

        return $tileNames;
    }
    //add event model functions

    public function processTilesData($postData, $files, $eventId, $allTiles = [])
    {
        $tiles = [];

        // Process each tile
        foreach ($allTiles as $tile) {
            $slug = $tile['slug'];  // Database slug (with underscores)
            $postKey = $tile['post_key'];  // Key used in $_POST and $_FILES
            $subsectionsData = $tile['subsections'] ?? [];

            // Initialize tile structure
            $validSubsections = [];

            // Process each subsection
            foreach ($subsectionsData as $index => $subsection) {
                // Upload PDFs using the POST key (which matches the $_FILES structure)
                $uploadedPdfs = $this->uploadSubsectionFiles($files, $postKey, $index, $eventId);

                // CRITICAL: Only add subsection if it has PDFs
                if (!empty($uploadedPdfs)) {
                    $validSubsections[] = [
                        'name' => $subsection['name'] ?? '',
                        'pdfs' => $uploadedPdfs
                    ];
                }
            }

            // CRITICAL: Only add tile if it has at least one valid subsection with PDFs
            if (!empty($validSubsections)) {
                $tiles[$slug] = [
                    'type' => $tile['type'] ?? 'other',
                    'sections' => count($validSubsections),
                    'subsections' => $validSubsections
                ];
            }
        }

        return $tiles;
    }

    public function saveTilesAsNestedCollection($eventId, $tiles)
    {
        if (!$eventId || empty($tiles)) {
            return false;
        }

        $now = round(microtime(true) * 1000);

        foreach ($tiles as $tileKey => $tileData) {
            if (!is_array($tileData))
                continue;

            $collection = strtolower($tileKey);
            $tileType = strtolower($tileData['type'] ?? 'main');

            // Save each subsection as its own document
            if (!empty($tileData['subsections']) && is_array($tileData['subsections'])) {
                foreach ($tileData['subsections'] as $subsection) {
                    $doc = [
                        'name' => $subsection['name'] ?? '',
                        'pdfs' => $subsection['pdfs'] ?? [],
                        'type' => $tileType,
                        'created_at' => $now,
                        'updated_at' => $now
                    ];

                    // Each subsection gets a unique Firestore doc ID
                    $this->firebase->setDocumentByPath(
                        "events/{$eventId}/{$collection}/" . uniqid(),
                        $doc
                    );
                }
            }
        }

        return true;
    }

    public function addEvent($eventData)
    {
        return $this->firebase->setDocument('events', $eventData);
    }
    //update events model functions:
    public function processTilesDataForUpdate($postData, $files, $eventId, $allTiles = [])
    {
        $tiles = [];

        foreach ($allTiles as $tile) {
            $slug = $tile['slug'];
            $postKey = $tile['post_key'];
            $subsectionsData = $tile['subsections'] ?? [];

            $existingTileData = $this->getEventTileData($eventId, $slug);
            $postSubsections = $postData[$postKey]['subsections'] ?? [];
            $usedDocIds = [];
            $validSubsections = [];

            foreach ($subsectionsData as $frontendIndex => $subsection) {
                $subsectionName = $subsection['name'] ?? '';
                $docId = $postSubsections[$frontendIndex]['key'] ?? uniqid();

                // Decode Base64-encoded URLs
                $keptPdfPaths = [];
                if (isset($postSubsections[$frontendIndex]['existing_pdfs'])) {
                    $rawPaths = is_array($postSubsections[$frontendIndex]['existing_pdfs'])
                        ? $postSubsections[$frontendIndex]['existing_pdfs']
                        : [$postSubsections[$frontendIndex]['existing_pdfs']];

                    foreach ($rawPaths as $encodedPath) {
                        $decodedPath = base64_decode($encodedPath);
                        if ($decodedPath !== false) {
                            $keptPdfPaths[] = $decodedPath;
                        }
                    }
                }

                $newPaths = $this->uploadSubsectionFiles($files, $tile['post_key'], $frontendIndex, $eventId);
                $allPaths = array_merge($keptPdfPaths, $newPaths);

                // CRITICAL: Only process subsection if it has PDFs
                if (!empty($allPaths)) {
                    $usedDocIds[] = $docId;

                    // Delete removed PDFs
                    $existingSubsectionData = $existingTileData[$docId] ?? [];
                    $existingPaths = $existingSubsectionData['pdfs'] ?? [];
                    $deletedPaths = array_diff($existingPaths, $allPaths);

                    foreach ($deletedPaths as $deletedPath) {
                        $this->deleteFirebaseFileFromUrl($deletedPath);
                    }

                    $validSubsections[$docId] = [
                        'name' => $subsectionName,
                        'pdfs' => $allPaths
                    ];
                } else {
                    // Subsection has no PDFs - mark for deletion if it exists
                    if (isset($existingTileData[$docId])) {
                        // Delete the document and its PDFs
                        $this->firebase->deleteDocument("events/{$eventId}/{$slug}", $docId);

                        if (isset($existingTileData[$docId]['pdfs'])) {
                            foreach ($existingTileData[$docId]['pdfs'] as $filePath) {
                                $this->deleteFirebaseFileFromUrl($filePath);
                            }
                        }
                    }
                }
            }

            // Delete removed subsections (those not in usedDocIds)
            if (!empty($existingTileData)) {
                $existingDocIds = array_keys($existingTileData);
                $docIdsToDelete = array_diff($existingDocIds, $usedDocIds);

                foreach ($docIdsToDelete as $docIdToDelete) {
                    $this->firebase->deleteDocument("events/{$eventId}/{$slug}", $docIdToDelete);

                    if (isset($existingTileData[$docIdToDelete]['pdfs'])) {
                        foreach ($existingTileData[$docIdToDelete]['pdfs'] as $filePath) {
                            $this->deleteFirebaseFileFromUrl($filePath);
                        }
                    }
                }
            }

            // CRITICAL: Only add tile if it has at least one valid subsection with PDFs
            if (!empty($validSubsections)) {
                $tiles[$slug] = [
                    'type' => $tile['type'] ?? 'other',
                    'sections' => count($validSubsections),
                    'subsections' => $validSubsections
                ];
            }
        }

        return $tiles;
    }
    public function updateTilesAsNestedCollection($eventId, $tiles)
    {
        if (!$eventId || empty($tiles)) return false;

        $now = round(microtime(true) * 1000);

        foreach ($tiles as $tileKey => $tileData) {
            if (!is_array($tileData)) continue;

            $collection = strtolower($tileKey);
            $tileType = strtolower($tileData['type'] ?? 'main');

            foreach ($tileData['subsections'] as $docId => $subsection) {
                $existingDoc = $this->firebase->getDocument("events/{$eventId}/{$collection}", $docId);

                $doc = [
                    'name' => $subsection['name'] ?? '',
                    'pdfs' => $subsection['pdfs'] ?? [], // file paths only
                    'type' => $tileType,
                    'created_at' => $existingDoc['created_at'] ?? $now,
                    'updated_at' => $now
                ];

                $this->firebase->setDocumentByPath("events/{$eventId}/{$collection}/{$docId}", $doc);
            }
        }

        return true;
    }
    public function deleteTileSubcollection($eventId, $tileSlug)
    {
        try {
            $documents = $this->firebase->getCollection("events/{$eventId}/{$tileSlug}");

            foreach ($documents as $docId => $docData) {
                // Delete PDFs from storage if they exist
                if (isset($docData['pdfs']) && is_array($docData['pdfs'])) {
                    foreach ($docData['pdfs'] as $pdfUrl) {
                        $this->deleteFirebaseFileFromUrl($pdfUrl);
                    }
                }

                // Delete the Firestore document
                $this->firebase->deleteDocument(
                    "events/{$eventId}/{$tileSlug}",
                    $docId
                );
            }

            return true;
        } catch (Exception $e) {
            log_message('error', 'Error deleting tile subcollection: ' . $e->getMessage());
            return false;
        }
    }
    public function deleteEventNestedCollection($eventId, $collectionName)
    {
        if (!$eventId || !$collectionName) {
            return false;
        }

        // Get all documents in this specific subcollection
        $documents = $this->firebase->getCollection("events/{$eventId}/{$collectionName}");

        // Delete each document
        foreach ($documents as $docId => $docData) {
            $this->firebase->deleteDocument("events/{$eventId}/{$collectionName}", $docId);

            // Also delete associated files if they exist
            if (isset($docData['pdfs']) && is_array($docData['pdfs'])) {
                foreach ($docData['pdfs'] as $pdfUrl) {
                    $this->deleteFirebaseFileFromUrl($pdfUrl);
                }
            }
        }

        return true;
    }

    private function uploadSubsectionFiles($files, $tileKey, $subsectionIndex, $eventId = null)
    {
        $uploadedUrls = [];

        // Check if this tile has any files uploaded
        if (!isset($files[$tileKey]) || !isset($files[$tileKey]['tmp_name']['subsections'][$subsectionIndex]['pdf'])) {
            return $uploadedUrls;
        }

        $tmpNames = $files[$tileKey]['tmp_name']['subsections'][$subsectionIndex]['pdf'];
        $errors = $files[$tileKey]['error']['subsections'][$subsectionIndex]['pdf'];
        $names = $files[$tileKey]['name']['subsections'][$subsectionIndex]['pdf'];

        // Files are already arrays in your structure, so process them directly
        foreach ($tmpNames as $index => $tmpFile) {
            // Check if file was uploaded successfully and tmp file exists
            if (isset($errors[$index]) && $errors[$index] === UPLOAD_ERR_OK && !empty($tmpFile) && is_uploaded_file($tmpFile)) {
                $folder = $eventId ? $eventId : 'temp_' . time();
                $originalName = $names[$index];

                $cleanName = preg_replace('/[^a-zA-Z0-9\.]+/', '_', $originalName);
                $cleanName = preg_replace('/_+/', '_', $cleanName);
                $cleanName = trim($cleanName, '_');

                $ext = pathinfo($cleanName, PATHINFO_EXTENSION);
                $nameOnly = pathinfo($cleanName, PATHINFO_FILENAME);

                $filename = $nameOnly . '_' . round(microtime(true) * 1000) . '.' . $ext;
                $firebasePath = "events/{$folder}/{$tileKey}/{$subsectionIndex}/{$filename}";

                // Upload to Firebase Storage
                $url = $this->firebase->uploadFile($tmpFile, $firebasePath);

                if ($url) {
                    $uploadedUrls[] = $url;
                }
            }
        }

        return $uploadedUrls;
    }
    private function deleteFirebaseFileFromUrl($url)
    {
        if (strpos($url, 'events/') === false) {
            return false;
        }

        $urlParts = parse_url($url);
        if (!isset($urlParts['path'])) {
            return false;
        }

        $path = $urlParts['path'];

        // Extract path from Firebase Storage URL format
        if (strpos($path, '/o/') !== false) {
            $path = explode('/o/', $path)[1];
            $path = urldecode($path);
            $path = explode('?', $path)[0];

            return $this->firebase->deleteFile($path);
        }

        return false;
    }
    public function updateEvent($eventId, $eventData)
    {
        return $this->firebase->updateDocument($this->table, $eventId, $eventData);
    }

    /**
     * Delete all nested collections for an event
     * 
     * @param string $eventId Event ID
     * @return bool Success status
     */
    public function deleteEventNestedCollections($eventId)
    {
        if (!$eventId) {
            return false;
        }

        // Get list of all subcollections
        $subcollections = $this->firebase->listSubcollections('events', $eventId);

        foreach ($subcollections as $collectionName) {
            // Get all documents in this subcollection
            $documents = $this->firebase->getCollection("events/{$eventId}/{$collectionName}");

            // Delete each document
            foreach ($documents as $docId => $docData) {
                $this->firebase->deleteDocument("events/{$eventId}/{$collectionName}", $docId);
            }
        }

        return true;
    }


    public function getEventById($id)
    {
        $document = $this->firebase->getDocument($this->table, $id);

        if (!$document) {
            return null;
        }

        // Fetch all subcollections
        $subcollections = $this->firebase->listSubcollections($this->table, $id); // you need a method for this

        foreach ($subcollections as $collectionName) {
            $docs = $this->firebase->getCollection("{$this->table}/{$id}/{$collectionName}");
            $document[$collectionName] = $docs; // attach subcollection documents
        }

        return $document;
    }
    public function getEventUsers($eventId)
    {
        $documents = $this->firebase->getCollection($this->table);

        if (!isset($documents[$eventId])) {
            return []; // event not found
        }

        $data = $documents[$eventId];

        // Cast to array in case it's an object
        $eventMembers = isset($data['event_members']) ? (array) $data['event_members'] : [];

        return array_keys($eventMembers); // return array of user IDs
    }


    public function validateEventData($eventData)
    {
        $errors = [];

        if (empty($eventData['event_name'])) {
            $errors[] = 'Event name is required';
        }

        if (empty($eventData['start_date'])) {
            $errors[] = 'Start date is required';
        }

        if (empty($eventData['end_date'])) {
            $errors[] = 'End date is required';
        }

        if (!empty($eventData['start_date']) && !empty($eventData['end_date'])) {
            $startTimestamp = strtotime($eventData['start_date']);
            $endTimestamp = strtotime($eventData['end_date']);

            if ($endTimestamp <= $startTimestamp) {
                $errors[] = 'End date must be after start date';
            }
        }

        return [
            'valid' => empty($errors),
            'errors' => $errors
        ];
    }

    public function deleteEvent($id)
    {
        return $this->firebase->deleteDocument($this->table, $id);
    }

    public function deleteEventFiles($eventId)
    {
        $event = $this->getEventById($eventId);

        if (!$event || !isset($event['tiles'])) {
            return false;
        }

        // Delete all PDFs from Firebase Storage
        foreach ($event['tiles'] as $tileKey => $tile) {
            if (isset($tile['subsections'])) {
                foreach ($tile['subsections'] as $subsection) {
                    if (isset($subsection['pdfs'])) {
                        foreach ($subsection['pdfs'] as $pdfUrl) {
                            $this->deleteFirebaseFileFromUrl($pdfUrl);
                        }
                    }
                }
            }
        }

        return true;
    }




    // ---------------- SCHEDULE MODEL ----------------

    public function getAllSchedules()
    {
        $documents = $this->firebase->getCollection($this->scheduleTable);
        $schedules = [];

        foreach ($documents as $id => $data) {
            // Convert milliseconds to seconds for PHP date() function
            $start_seconds = isset($data['date']) ? intval($data['date'] / 1000) : 0;

            $schedules[] = [
                'id' => $id,
                'name' => $data['name'] ?? 'N/A',
                'date' => $start_seconds ? date('M d, Y H:i', $start_seconds) : 'N/A',
                'host' => $data['host'] ?? 'N/A',
                'location' => $data['location'] ?? 'N/A',
                'img' => $data['img'] ?? null,
                'start_ms' => $data['date'] ?? 0,
                'end_ms' => $data['end_date'] ?? 0
            ];
        }
        return $schedules;
    }
    public function schedulesForDashboard()
    {
        $documents = $this->firebase->getCollection($this->scheduleTable);
        $schedules = [];

        foreach ($documents as $id => $data) {
            $schedules[] = [
                'id' => $id,
                'name' => $data['name'] ?? 'N/A',
                'date' => isset($data['date']) ? date('M d, Y H:i', strtotime($data['date'])) : 'N/A',
                'host' => $data['host'] ?? 'N/A',
                'location' => $data['location'] ?? 'N/A',
            ];
        }

        return array_slice($schedules, 0, 5);
    }

    public function countEventsByStatus($status)
    {
        $documents = $this->firebase->getCollection($this->table);
        $count = 0;
        $now = time(); // seconds

        foreach ($documents as $id => $data) {

            if (
                isset($data['status'], $data['start_date'], $data['end_date']) &&
                strtolower($data['status']) === strtolower($status)
            ) {
                $start = $data['start_date'] / 1000; // ms → sec
                $end   = $data['end_date'] / 1000;

                // event is currently running
                if ($start <= $now && $end > $now) {
                    $count++;
                }
            }
        }

        return $count;
    }

    public function countPastEvents()
    {
        $documents = $this->firebase->getCollection($this->table);
        $count = 0;
        $now = time(); // current time in seconds

        foreach ($documents as $id => $data) {
            // Make sure end_date exists
            if (isset($data['end_date'])) {
                // Firebase stores timestamps in milliseconds, divide by 1000
                $endTimestamp = $data['end_date'] / 1000;
                if ($endTimestamp < $now) {
                    $count++;
                }
            }
        }

        return $count;
    }

    public function addSchedule($data)
    {
        return $this->firebase->setDocument($this->scheduleTable, $data);
    }

    public function getScheduleById($id)
    {
        return $this->firebase->getDocument($this->scheduleTable, $id);
    }

    public function updateSchedule($id, $data)
    {
        return $this->firebase->updateDocument($this->scheduleTable, $id, $data);
    }

    public function deleteSchedule($id)
    {
        return $this->firebase->deleteDocument($this->scheduleTable, $id);
    }
    //helper functions
    public function generateEventId()
    {
        // Create a new Firestore doc reference and get its ID without writing data yet
        return $this->firebase->generateDocumentId('events');
    }

    public function getEventInfoById($eventId)
    {
        if (empty($eventId)) {
            return [
                'event_name' => 'N/A',
                'start_date' => 'N/A'
            ];
        }

        $event = $this->firebase->getDocument($this->table, $eventId);

        if (!$event) {
            return [
                'event_name' => 'N/A',
                'start_date' => 'N/A'
            ];
        }

        // Format the date if you want it human-readable
        $startDate = isset($event['start_date'])
            ? date('M d, Y', $event['start_date'] / 1000)
            : 'N/A';

        return [
            'event_name' => $event['event_name'] ?? 'N/A',
            'start_date' => $startDate
        ];
    }



    public function getEventTileData($eventId, $tileSlug)
    {
        try {
            $documents = $this->firebase->db()
                ->collection("events/{$eventId}/{$tileSlug}")
                ->documents();

            $result = [];
            foreach ($documents as $doc) {
                if ($doc->exists()) {
                    $result[$doc->id()] = $doc->data();
                }
            }

            return $result;
        } catch (Exception $e) {
            log_message('error', 'Error getting tile data: ' . $e->getMessage());
            return null;
        }
    }



    private function deletePdfFromStorage($pdfUrl)
    {
        try {
            // Extract the storage path from the URL
            // URL format: https://storage.googleapis.com/bucket/path?params
            $urlParts = parse_url($pdfUrl);

            if (!isset($urlParts['path'])) {
                return false;
            }

            // Remove leading slash and bucket name from path
            $path = ltrim($urlParts['path'], '/');

            // Remove bucket name if present
            $bucketName = 'ringsideproduction.firebasestorage.app';
            if (strpos($path, $bucketName . '/') === 0) {
                $path = substr($path, strlen($bucketName) + 1);
            }

            // Delete file from storage
            return $this->firebase->deleteFile($path);
        } catch (Exception $e) {
            log_message('error', 'Error deleting PDF from storage: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * Get tile by slug
     * 
     * @param string $slug Tile slug
     * @return array|null Tile data
     */
    public function getTileBySlug($slug)
    {
        try {
            $tiles = $this->firebase->getCollection('tiles');

            foreach ($tiles as $tileId => $tile) {
                if (isset($tile['slug']) && $tile['slug'] === $slug) {
                    $tile['tile_id'] = $tileId;
                    return $tile;
                }
            }

            return null;
        } catch (Exception $e) {
            log_message('error', 'Error getting tile by slug: ' . $e->getMessage());
            return null;
        }
    }



    public function getSignedUrl($filePath, $expires = 3600)
    {
        return $this->firebase->generateSignedUrl($filePath, $expires);
    }
    public function getTiles($useCache = true)
    {
        if ($useCache && $this->tilesCache !== null) {
            return $this->tilesCache;
        }

        $documents = $this->firebase->getCollection('tiles');
        $tiles = [];

        foreach ($documents as $id => $data) {
            // Only include tiles with type "main"
            $type = isset($data['type']) ? $data['type'] : 'main';
            if ($type !== 'main') continue;

            // Skip admin_chat tile
            $slug = $data['slug'] ?? 'n_a';
            if ($slug === 'admin_chat') continue;

            $tiles[] = [
                'tile_id'   => $id,
                'tile_name' => $data['tile_name'] ?? 'N/A',
                'tile_url'  => $data['tile_url'] ?? null,
                'type'      => $type,
                'slug'      => $slug,
            ];
        }

        // Cache the result
        $this->tilesCache = $tiles;

        return $tiles;
    }

    public function getTileById($tileId)
    {
        $data = $this->firebase->getDocument('tiles', $tileId);
        if (!$data) return null;

        return [
            'tile_id'   => $tileId,
            'tile_name' => $data['tile_name'] ?? 'N/A',
            'tile_url'  => $data['tile_url'] ?? null,
            'type'      => $data['type'] ?? 'other',
            'slug'      => $data['slug'] ?? 'n_a',
        ];
    }


    public function insertTile($data)
    {
        if (!isset($data['tile_id'])) {
            throw new \Exception("Tile ID is required");
        }

        return $this->firebase->setDocumentWithId($this->tiles, $data['tile_id'], $data);
    }
}
