<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Csrf;
use App\Repositories\Container;

class AdminController
{
    public function overview(): void
    {
        $users = Container::users()->all(['role' => 'CUSTOMER']);
        $appts = Container::appointments();
        $stats = [
            'customers' => count($users),
            'artists'   => count(Container::artists()->all()),
            'pending'   => count($appts->byStatus('PENDING')),
            'completed' => count($appts->byStatus('COMPLETED')),
        ];
        $recent = array_slice($appts->all(), 0, 10);
        render('admin', 'admin.overview', compact('stats', 'recent'), t('admin.overview.title'));
    }

    public function users(): void
    {
        $q = trim((string)($_GET['q'] ?? ''));
        $list = Container::users()->search($q, 'CUSTOMER', 100);
        render('admin', 'admin.users', compact('list', 'q'), t('admin.users.title'));
    }

    public function userDetail(array $params): void
    {
        $user = Container::users()->find($params['id'] ?? '');
        if (!$user) { http_response_code(404); require MAT_ROOT . '/src/Views/errors/404.php'; return; }
        $appointments = Container::appointments()->forCustomer($user['id']);
        $forms = Container::intakeForms()->forCustomer($user['id']);
        render('admin', 'admin.user-detail', compact('user', 'appointments', 'forms'), ($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? ''));
    }

    public function gallery(): void
    {
        $items = Container::gallery()->all();
        $artists = Container::artists()->all();
        render('admin', 'admin.gallery', compact('items', 'artists'), t('admin.gallery.title'));
    }

    private function isXhr(): bool
    {
        return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
    }

    private function galleryResponse(bool $ok, string $message): void
    {
        if ($this->isXhr()) {
            header('Content-Type: application/json');
            http_response_code($ok ? 200 : 422);
            echo json_encode(['ok' => $ok, 'message' => $message]);
            exit;
        }
        $_SESSION['_flash'][$ok ? 'success' : 'error'] = $message;
        redirect('/admin/gallery');
    }

    public function galleryAdd(): void
    {
        Csrf::requireValid();

        $videoUrl = trim((string)($_POST['video_url'] ?? ''));
        $thumbUrl = trim((string)($_POST['thumb_url'] ?? ''));

        // Check for upload errors FIRST (file too large, etc.)
        if (!empty($_FILES['file'])) {
            $err = $_FILES['file']['error'] ?? UPLOAD_ERR_OK;
            if ($err === UPLOAD_ERR_INI_SIZE || $err === UPLOAD_ERR_FORM_SIZE) {
                $maxSize = \ini_get('upload_max_filesize') ?: '2M';
                $this->galleryResponse(false, t('admin.gallery.file_too_large') . ' (max: ' . $maxSize . '). Restart the server with: php -d upload_max_filesize=100M -d post_max_size=105M -S localhost:8765 -t public');
            }
            if ($err !== UPLOAD_ERR_OK && $err !== UPLOAD_ERR_NO_FILE) {
                $this->galleryResponse(false, t('admin.gallery.upload_failed') . ' (error code ' . $err . ')');
            }
        }

        $hasFile = !empty($_FILES['file']) && !empty($_FILES['file']['tmp_name']);

        if (!$hasFile && $videoUrl === '') {
            $this->galleryResponse(false, t('admin.gallery.nothing_to_save'));
        }

        // Path 1: a pasted video URL (YouTube / Vimeo / remote MP4)
        if ($videoUrl !== '' && !$hasFile) {
            $vp = video_provider($videoUrl);
            if ($vp['provider'] === 'link') {
                $this->galleryResponse(false, t('admin.gallery.unsupported_url'));
            }
            Container::gallery()->save([
                'kind'      => 'VIDEO',
                'url'       => $videoUrl,
                'thumb_url' => $thumbUrl ?: null,
                'artist_id' => !empty($_POST['artist_id']) ? $_POST['artist_id'] : null,
                'caption'   => $_POST['caption'] ?? '',
                'tags'      => array_filter(array_map('trim', explode(',', $_POST['tags'] ?? ''))),
            ]);
            $this->galleryResponse(true, t('admin.gallery.added'));
        }

        // Path 2: a real file upload (image or MP4)
        $f = $_FILES['file'];
        if (!empty($f['error']) && $f['error'] !== UPLOAD_ERR_OK) {
            $this->galleryResponse(false, t('admin.gallery.upload_failed') . ' (code ' . $f['error'] . ')');
        }
        $allowed = [
            'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp',
            'image/gif' => 'gif',
            'video/mp4'  => 'mp4', 'video/quicktime' => 'mov', 'video/webm' => 'webm',
        ];
        $mime = function_exists('mime_content_type') ? (@\mime_content_type($f['tmp_name']) ?: '') : '';
        if (!$mime || !isset($allowed[$mime])) {
            $ext = strtolower(\pathinfo($f['name'] ?? '', PATHINFO_EXTENSION));
            $extMap = ['jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'webp' => 'image/webp', 'gif' => 'image/gif', 'mp4' => 'video/mp4', 'mov' => 'video/quicktime', 'webm' => 'video/webm'];
            $mime = $extMap[$ext] ?? $mime;
        }
        if (!isset($allowed[$mime])) {
            $this->galleryResponse(false, t('admin.gallery.unsupported') . ' (' . ($mime ?: 'unknown') . ')');
        }
        $name = uuid() . '.' . $allowed[$mime];
        $galleryDir = config('upload_path') . DIRECTORY_SEPARATOR . 'gallery';
        if (!is_dir($galleryDir)) { @mkdir($galleryDir, 0755, true); }
        $dest = $galleryDir . DIRECTORY_SEPARATOR . $name;
        if (!@move_uploaded_file($f['tmp_name'], $dest)) {
            $this->galleryResponse(false, t('admin.gallery.upload_failed'));
        }
        Container::gallery()->save([
            'kind'      => str_starts_with($mime, 'video') ? 'VIDEO' : 'IMAGE',
            'url'       => config('upload_url') . '/gallery/' . $name,
            'thumb_url' => $thumbUrl ?: null,
            'artist_id' => !empty($_POST['artist_id']) ? $_POST['artist_id'] : null,
            'caption'   => $_POST['caption'] ?? '',
            'tags'      => array_filter(array_map('trim', explode(',', $_POST['tags'] ?? ''))),
        ]);
        $this->galleryResponse(true, t('admin.gallery.added'));
    }

    public function galleryDelete(array $params): void
    {
        Csrf::requireValid();
        Container::gallery()->delete($params['id'] ?? '');
        $_SESSION['_flash']['success'] = t('admin.gallery.deleted');
        redirect('/admin/gallery');
    }

    public function audit(): void
    {
        $userRepo = Container::users();
        $search   = trim((string)($_GET['q'] ?? ''));
        $filterStaff  = trim((string)($_GET['staff'] ?? ''));
        $filterAction = trim((string)($_GET['action'] ?? ''));

        $filters = [];
        if ($filterStaff)  $filters['staff_id'] = $filterStaff;
        if ($filterAction) $filters['action']   = $filterAction;

        $entries = Container::audit()->all($filters, 500);

        // Free-text search across staff name, action, target
        if ($search) {
            $q = strtolower($search);
            $entries = array_values(array_filter($entries, function ($e) use ($q, $userRepo) {
                $u = $userRepo->find($e['staff_id'] ?? '');
                $staffName = $u ? strtolower(trim(($u['first_name'] ?? '') . ' ' . ($u['last_name'] ?? '') . ' ' . ($u['username'] ?? ''))) : '';
                $haystack = $staffName . ' ' . strtolower($e['action'] ?? '') . ' ' . strtolower($e['target_type'] ?? '') . ' ' . strtolower($e['target_id'] ?? '');
                return str_contains($haystack, $q);
            }));
        }

        // Collect unique staff + actions for filter dropdowns
        $allEntries = Container::audit()->all([], 2000);
        $staffIds = array_unique(array_filter(array_column($allEntries, 'staff_id')));
        $staffOptions = [];
        foreach ($staffIds as $sid) {
            $u = $userRepo->find($sid);
            $staffOptions[$sid] = $u ? trim(($u['first_name'] ?? '') . ' ' . ($u['last_name'] ?? '')) : $sid;
        }
        asort($staffOptions);
        $actionOptions = array_unique(array_filter(array_column($allEntries, 'action')));
        sort($actionOptions);

        render('admin', 'admin.audit', compact('entries', 'userRepo', 'search', 'filterStaff', 'filterAction', 'staffOptions', 'actionOptions'), t('admin.audit.title'));
    }

    public function settings(): void
    {
        $settings = Container::settings()->get();
        render('admin', 'admin.settings', compact('settings'), t('admin.settings.title'));
    }

    public function saveSettings(): void
    {
        Csrf::requireValid();
        // Build hours from the split start/end/closed inputs
        $hours = [];
        foreach (['mon','tue','wed','thu','fri','sat','sun'] as $d) {
            if (!empty($_POST['hours_closed'][$d])) {
                $hours[$d] = 'closed';
            } else {
                $s = $_POST['hours_start'][$d] ?? '09:00';
                $e = $_POST['hours_end'][$d]   ?? '16:00';
                $hours[$d] = $s . '-' . $e;
            }
        }
        // Build SMTP config (only save non-empty values to allow config.php fallback)
        $smtp = [];
        $smtpFields = ['host','port','username','password','from_email','from_name'];
        foreach ($smtpFields as $f) {
            $v = trim((string)($_POST['smtp_' . $f] ?? ''));
            if ($v !== '') $smtp[$f] = $f === 'port' ? (int)$v : $v;
        }

        $payload = [
            'shop_name'     => trim((string)($_POST['shop_name'] ?? '')),
            'tagline_en'    => trim((string)($_POST['tagline_en'] ?? '')),
            'tagline_es'    => trim((string)($_POST['tagline_es'] ?? '')),
            'address'       => trim((string)($_POST['address'] ?? '')),
            'phone'         => trim((string)($_POST['phone'] ?? '')),
            'email'         => trim((string)($_POST['email'] ?? '')),
            'hours'         => $hours,
            'socials'       => $_POST['socials'] ?? [],
            'map_embed_url'     => trim((string)($_POST['map_embed_url'] ?? '')),
            'google_review_url' => trim((string)($_POST['google_review_url'] ?? '')),
            'smtp'              => $smtp,
        ];
        Container::settings()->save($payload);
        $_SESSION['_flash']['success'] = t('admin.settings.saved');
        redirect('/admin/settings');
    }

    public function testEmail(): void
    {
        Csrf::requireValid();
        $to = trim((string)($_POST['test_email_to'] ?? ''));
        if (!$to || !filter_var($to, FILTER_VALIDATE_EMAIL)) {
            $_SESSION['_flash']['error'] = t('admin.smtp.test_invalid_email');
            redirect('/admin/settings');
        }
        $ok = \App\Services\Email::send($to,
            'Test email from Mystic Art Tattoo',
            \App\Services\Email::template('Test email',
                '<p>If you can read this, your email configuration is working correctly.</p><p style="color:rgba(245,245,242,0.5);font-size:13px">Sent from the Mystic Art Tattoo admin panel.</p>')
        );
        $_SESSION['_flash'][$ok ? 'success' : 'error'] = $ok ? t('admin.smtp.test_sent') : t('admin.smtp.test_failed');
        redirect('/admin/settings');
    }

    /**
     * Export all data as a single organized JSON file (download).
     */
    public function exportData(): void
    {
        $export = [
            'exported_at' => now_iso(),
            'shop_settings' => Container::settings()->get(),
            'users'         => Container::users()->all(),
            'artists'       => Container::artists()->all(),
            'appointments'  => Container::appointments()->all(),
            'intake_forms'  => Container::intakeForms()->all(),
            'gallery'       => Container::gallery()->all(),
            'audit_log'     => Container::audit()->all([], 10000),
            'schedules'     => [
                'weekly'     => [],
                'exceptions' => [],
            ],
        ];

        // Pull schedules for every artist
        foreach ($export['artists'] as $a) {
            $weekly = Container::schedules()->weeklyForArtist($a['id']);
            foreach ($weekly as $w) { $export['schedules']['weekly'][] = $w; }
        }

        $filename = 'mysticart-backup-' . date('Y-m-d-His') . '.json';
        header('Content-Type: application/json');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        echo json_encode($export, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        exit;
    }

    /**
     * Clear all appointments and customer data. Requires admin password confirmation.
     * Staff/artist accounts and settings are preserved.
     */
    public function clearData(): void
    {
        Csrf::requireValid();
        $password = (string)($_POST['admin_password'] ?? '');
        $user = \App\Auth::user();
        if (!$user || empty($user['password_hash']) || !password_verify($password, $user['password_hash'])) {
            $_SESSION['_flash']['error'] = t('admin.data.wrong_password');
            redirect('/admin/settings');
        }

        $what = $_POST['clear_what'] ?? 'appointments';

        if ($what === 'appointments' || $what === 'all') {
            // Clear all appointments
            $allAppts = Container::appointments()->all();
            foreach ($allAppts as $a) {
                Container::appointments()->delete($a['id']);
            }
        }

        if ($what === 'all') {
            // Clear all customer records (keep STAFF/ADMIN/ARTIST)
            $allUsers = Container::users()->all();
            foreach ($allUsers as $u) {
                if (($u['role'] ?? '') === 'CUSTOMER') {
                    Container::users()->delete($u['id']);
                }
            }
            // Clear all intake forms
            $allForms = Container::intakeForms()->all();
            foreach ($allForms as $f) {
                Container::intakeForms()->delete($f['id']);
            }
        }

        Container::audit()->log($user['id'], 'CLEAR_DATA', 'system', $what);
        $_SESSION['_flash']['success'] = t('admin.data.cleared');
        redirect('/admin/settings');
    }

    /**
     * Import data from a previously exported JSON backup.
     */
    public function importData(): void
    {
        Csrf::requireValid();
        $password = (string)($_POST['admin_password'] ?? '');
        $user = \App\Auth::user();
        if (!$user || empty($user['password_hash']) || !password_verify($password, $user['password_hash'])) {
            $_SESSION['_flash']['error'] = t('admin.data.wrong_password');
            redirect('/admin/settings');
        }

        if (empty($_FILES['import_file']) || empty($_FILES['import_file']['tmp_name'])) {
            $_SESSION['_flash']['error'] = t('admin.data.no_file');
            redirect('/admin/settings');
        }

        $json = file_get_contents($_FILES['import_file']['tmp_name']);
        $data = json_decode($json, true);
        if (!$data || !is_array($data)) {
            $_SESSION['_flash']['error'] = t('admin.data.invalid_file');
            redirect('/admin/settings');
        }

        $imported = 0;
        if (!empty($data['appointments'])) {
            foreach ($data['appointments'] as $a) { Container::appointments()->save($a); $imported++; }
        }
        if (!empty($data['users'])) {
            foreach ($data['users'] as $u) { Container::users()->save($u); $imported++; }
        }
        if (!empty($data['intake_forms'])) {
            foreach ($data['intake_forms'] as $f) { Container::intakeForms()->save($f); $imported++; }
        }

        Container::audit()->log($user['id'], 'IMPORT_DATA', 'system', (string)$imported . ' records');
        $_SESSION['_flash']['success'] = t('admin.data.imported', ['count' => $imported]);
        redirect('/admin/settings');
    }
}
