<?php

declare(strict_types=1);

namespace Lab\Controllers;

use Lab\Auth;
use Lab\Flash;
use Lab\Helpers;
use Lab\License;
use Lab\OrderStore;
use Lab\Output;
use Lab\Products;
use Lab\Settings;
use Lab\View;

final class StudioController
{
    public function __construct(
        private array $config,
        private Auth $auth,
        private Products $products,
        private OrderStore $orders,
        private Output $output,
        private License $license,
    ) {}

    public function showLogin(): void
    {
        if ($this->auth->adminCheck()) {
            View::redirect('/studio');
        }
        View::render('studio/login', ['title' => 'Studio']);
    }

    public function login(): void
    {
        if (! Helpers::verifyCsrf($_POST['csrf_token'] ?? null)) {
            Flash::set('error', 'Η ενέργεια απορρίφθηκε.');
            View::redirect('/studio/login');
        }
        $pin = trim((string) ($_POST['pin'] ?? ''));
        $user = trim((string) ($_POST['username'] ?? ''));
        $pass = (string) ($_POST['password'] ?? '');
        $ok = $pin !== '' ? $this->auth->attemptPin($pin) : $this->auth->attemptAdmin($user, $pass);
        if (! $ok) {
            Flash::set('error', 'Λάθος στοιχεία.');
            View::redirect('/studio/login');
        }
        View::redirect('/studio');
    }

    public function logout(): void
    {
        $this->auth->logout();
        View::redirect('/studio/login');
    }

    public function report(): void
    {
        $this->auth->requireAdmin();
        $orders = $this->orders->today();
        View::render('studio/report', [
            'title' => 'Ημερήσια αναφορά',
            'orders' => $orders,
            'stats' => $this->orders->stats(),
            'userName' => $this->auth->adminName(),
        ]);
    }

    public function index(): void
    {
        $this->auth->requireAdmin();
        $status = (string) ($_GET['status'] ?? 'all');
        $q = (string) ($_GET['q'] ?? '');
        View::render('studio/dashboard', [
            'title' => 'Παραγγελίες',
            'orders' => $this->orders->list($status, $q),
            'stats' => $this->orders->stats(),
            'status' => $status,
            'q' => $q,
            'userName' => $this->auth->adminName(),
            'stores' => $this->config['stores'] ?? [],
        ]);
    }

    public function show(int $id): void
    {
        $this->auth->requireAdmin();
        $order = $this->orders->find($id);
        if (! $order) {
            Flash::set('error', 'Η παραγγελία δεν βρέθηκε.');
            View::redirect('/studio');
        }
        $items = json_decode((string) $order['items_json'], true);
        View::render('studio/order', [
            'title' => $order['code'],
            'order' => $order,
            'items' => is_array($items) ? $items : [],
            'userName' => $this->auth->adminName(),
            'stores' => $this->config['stores'] ?? [],
            'products' => $this->products->map(),
            'printers' => Output::listPrinters(),
            'sizes' => $this->output->sizesInOrder($order),
            'printDir' => $this->printDirFor($order),
            'printerMap' => Settings::get()['printer_by_sku'] ?? [],
        ]);
    }

    public function ticket(int $id): void
    {
        $this->auth->requireAdmin();
        $order = $this->orders->find($id);
        if (! $order) {
            View::redirect('/studio');
        }
        $items = json_decode((string) $order['items_json'], true);
        View::render('studio/ticket', [
            'title' => 'Απόδειξη ' . $order['code'],
            'order' => $order,
            'items' => is_array($items) ? $items : [],
            'stores' => $this->config['stores'] ?? [],
        ]);
    }

    public function setStatus(int $id): void
    {
        $this->auth->requireAdmin();
        if (! Helpers::verifyCsrf($_POST['csrf_token'] ?? null)) {
            Flash::set('error', 'Η ενέργεια απορρίφθηκε.');
            View::redirect('/studio/orders/' . $id);
        }
        try {
            $this->orders->setStatus($id, (string) ($_POST['status'] ?? ''));
            Flash::set('success', 'Η κατάσταση ενημερώθηκε.');
        } catch (\Throwable $e) {
            Flash::set('error', $e->getMessage());
        }
        View::redirect('/studio/orders/' . $id);
    }

    public function export(int $id): void
    {
        $this->auth->requireAdmin();
        if (! Helpers::verifyCsrf($_POST['csrf_token'] ?? null)) {
            Flash::set('error', 'Η ενέργεια απορρίφθηκε.');
            View::redirect('/studio/orders/' . $id);
        }
        $order = $this->orders->find($id);
        if (! $order) {
            View::redirect('/studio');
        }
        try {
            $dir = $this->orders->exportHotfolder($order, $this->products->map());
            Flash::set('success', 'Στάλθηκε στο hot folder: ' . basename($dir));
        } catch (\Throwable $e) {
            Flash::set('error', $e->getMessage());
        }
        View::redirect('/studio/orders/' . $id);
    }

    public function zip(int $id): void
    {
        $this->auth->requireAdmin();
        $order = $this->orders->find($id);
        if (! $order) {
            View::redirect('/studio');
        }
        $path = $this->orders->zipOrder($order);
        header('Content-Type: application/zip');
        header('Content-Disposition: attachment; filename="' . basename($path) . '"');
        header('Content-Length: ' . filesize($path));
        readfile($path);
        exit;
    }

    public function photo(int $id, string $stored): void
    {
        $this->auth->requireAdmin();
        $order = $this->orders->find($id);
        if (! $order) {
            http_response_code(404);
            exit;
        }
        $path = $this->orders->originalPath($order, $stored);
        $mime = mime_content_type($path) ?: 'image/jpeg';
        header('Content-Type: ' . $mime);
        header('Cache-Control: private, max-age=120');
        readfile($path);
        exit;
    }

    public function products(): void
    {
        $this->auth->requireAdmin();
        View::render('studio/products', [
            'title' => 'Τιμοκατάλογος',
            'products' => $this->products->all(),
            'userName' => $this->auth->adminName(),
        ]);
    }

    public function saveProducts(): void
    {
        $this->auth->requireAdmin();
        if (! Helpers::verifyCsrf($_POST['csrf_token'] ?? null)) {
            Flash::set('error', 'Η ενέργεια απορρίφθηκε.');
            View::redirect('/studio/products');
        }
        $prices = $_POST['price'] ?? [];
        $active = $_POST['active'] ?? [];
        if (is_array($prices)) {
            foreach ($prices as $sku => $value) {
                $cents = (int) round(((float) str_replace(',', '.', (string) $value)) * 100);
                $on = isset($active[$sku]) ? 1 : 0;
                $this->products->updatePrice((string) $sku, $cents, $on);
            }
        }
        Flash::set('success', 'Ο τιμοκατάλογος αποθηκεύτηκε.');
        View::redirect('/studio/products');
    }

    public function settings(): void
    {
        $this->auth->requireAdmin();
        View::render('studio/settings', [
            'title' => 'Εκτυπωτές',
            'settings' => Settings::get(),
            'userName' => $this->auth->adminName(),
            'printers' => Output::listPrinters(),
            'products' => $this->products->all(),
        ]);
    }

    public function saveSettings(): void
    {
        $this->auth->requireAdmin();
        if (! Helpers::verifyCsrf($_POST['csrf_token'] ?? null)) {
            Flash::set('error', 'Η ενέργεια απορρίφθηκε.');
            View::redirect('/studio/settings');
        }
        Settings::save($_POST);
        Flash::set('success', 'Οι ρυθμίσεις αποθηκεύτηκαν.');
        View::redirect('/studio/settings');
    }

    public function browseFolder(): void
    {
        $this->auth->requireAdmin();
        $body = $_POST !== [] ? $_POST : Helpers::readJson();
        if (! Helpers::verifyCsrf(isset($body['csrf_token']) && is_string($body['csrf_token']) ? $body['csrf_token'] : null)) {
            Helpers::json(['ok' => false, 'error' => 'Η ενέργεια απορρίφθηκε.'], 403);
        }
        if (PHP_OS_FAMILY !== 'Windows') {
            Helpers::json(['ok' => false, 'path' => '', 'error' => 'Η αναζήτηση φακέλου ανοίγει στα Windows.']);
        }
        $current = trim((string) ($body['current'] ?? ''));
        $title = trim((string) ($body['title'] ?? 'Επιλογή φακέλου')) ?: 'Επιλογή φακέλου';
        $path = \Lab\Windows::browseFolder($current, $title);
        Helpers::json([
            'ok' => $path !== '',
            'path' => $path,
        ]);
    }

    public function addPrinter(): void
    {
        $this->auth->requireAdmin();
        $body = $_POST !== [] ? $_POST : Helpers::readJson();
        if (! Helpers::verifyCsrf(isset($body['csrf_token']) && is_string($body['csrf_token']) ? $body['csrf_token'] : null)) {
            Helpers::json(['ok' => false, 'error' => 'Η ενέργεια απορρίφθηκε.'], 403);
        }
        $ok = \Lab\Windows::openAddPrinter();
        Helpers::json([
            'ok' => $ok,
            'error' => $ok ? '' : 'Η σύνδεση εκτυπωτή ανοίγει στα Windows.',
        ]);
    }

    public function connectPrinter(): void
    {
        $this->auth->requireAdmin();
        $body = $_POST !== [] ? $_POST : Helpers::readJson();
        if (! Helpers::verifyCsrf(isset($body['csrf_token']) && is_string($body['csrf_token']) ? $body['csrf_token'] : null)) {
            Helpers::json(['ok' => false, 'error' => 'Η ενέργεια απορρίφθηκε.'], 403);
        }
        $name = trim((string) ($body['printer'] ?? $body['name'] ?? ''));
        $result = \Lab\Windows::connectPrinter($name);
        Helpers::json($result);
    }

    public function licenses(): void
    {
        $this->auth->requireAdmin();
        if (\Lab\License::isKiosk()) {
            View::redirect('/studio');
        }
        View::render('studio/licenses', [
            'title' => 'Άδειες',
            'licenses' => $this->license->all(),
            'issued' => $_SESSION['lab_issued_keys'] ?? [],
            'userName' => $this->auth->adminName(),
        ]);
        unset($_SESSION['lab_issued_keys']);
    }

    public function saveLicenses(): void
    {
        $this->auth->requireAdmin();
        if (\Lab\License::isKiosk()) {
            View::redirect('/studio');
        }
        if (! Helpers::verifyCsrf($_POST['csrf_token'] ?? null)) {
            Flash::set('error', 'Η ενέργεια απορρίφθηκε.');
            View::redirect('/studio/licenses');
        }
        $action = (string) ($_POST['action'] ?? 'issue');
        $id = (int) ($_POST['id'] ?? 0);
        try {
            if ($action === 'reset' && $id > 0) {
                $this->license->reset($id);
                Flash::set('success', 'Η συσκευή αποσυνδέθηκε. Το κλειδί μπορεί να ενεργοποιηθεί σε άλλον υπολογιστή.');
            } elseif ($action === 'revoke' && $id > 0) {
                $this->license->revoke($id, true);
                Flash::set('success', 'Το κλειδί απενεργοποιήθηκε.');
            } elseif ($action === 'restore' && $id > 0) {
                $this->license->revoke($id, false);
                Flash::set('success', 'Το κλειδί ενεργοποιήθηκε ξανά.');
            } else {
                $note = trim((string) ($_POST['note'] ?? ''));
                $count = (int) ($_POST['count'] ?? 1);
                $keys = $this->license->issue($note, $count);
                $_SESSION['lab_issued_keys'] = $keys;
                Flash::set('success', 'Εκδόθηκαν ' . count($keys) . ' κλειδιά. Κάθε κλειδί πιάνει μόνο έναν υπολογιστή.');
            }
        } catch (\Throwable $e) {
            Flash::set('error', $e->getMessage());
        }
        View::redirect('/studio/licenses');
    }

    public function printDnp(int $id): void
    {
        $this->auth->requireAdmin();
        if (! Helpers::verifyCsrf($_POST['csrf_token'] ?? null)) {
            Flash::set('error', 'Η ενέργεια απορρίφθηκε.');
            View::redirect('/studio/orders/' . $id);
        }
        $order = $this->orders->find($id);
        if (! $order) {
            View::redirect('/studio');
        }
        try {
            $printer = trim((string) ($_POST['printer'] ?? ''));
            $sku = (string) ($_POST['sku'] ?? 'all');
            $result = $this->output->sendDnp($order, $printer === '' ? null : $printer, $sku);
            $msg = (PHP_OS_FAMILY === 'Darwin' ? 'Mac' : 'Windows') . ': στάλθηκαν ' . $result['printed'] . ' εκτυπώσεις.';
            if ($result['copied'] !== '') {
                $msg .= ' Αντίγραφο και στο DNP hot folder: ' . $result['copied'];
            }
            if ($result['printed'] === 0 && $result['copied'] === '') {
                $msg = 'Ετοιμάστηκαν αρχεία στο ' . $result['folder'] . '. Διάλεξε εκτυπωτή στις ρυθμίσεις.';
            }
            Flash::set('success', $msg);
        } catch (\Throwable $e) {
            Flash::set('error', $e->getMessage());
        }
        View::redirect('/studio/orders/' . $id);
    }

    public function saveFiles(int $id): void
    {
        $this->auth->requireAdmin();
        if (! Helpers::verifyCsrf($_POST['csrf_token'] ?? null)) {
            Flash::set('error', 'Η ενέργεια απορρίφθηκε.');
            View::redirect('/studio/orders/' . $id);
        }
        $order = $this->orders->find($id);
        if (! $order) {
            View::redirect('/studio');
        }
        try {
            $dir = $this->output->saveFiles($order);
            Flash::set('success', 'Αποθηκεύτηκαν στο: ' . $dir);
        } catch (\Throwable $e) {
            Flash::set('error', $e->getMessage());
        }
        View::redirect('/studio/orders/' . $id);
    }

    private function printDirFor(array $order): string
    {
        $code = (string) ($order['code'] ?? '');
        if ($code === '') {
            return '';
        }
        $named = Helpers::orderFolderName($order);
        $candidates = [
            rtrim((string) (Settings::get()['save_dir'] ?? ''), '/\\') . DIRECTORY_SEPARATOR . $named,
            rtrim((string) (Settings::get()['save_dir'] ?? ''), '/\\') . DIRECTORY_SEPARATOR . $code,
            rtrim((string) ($this->config['print_dir'] ?? ''), '/') . '/' . $named,
            rtrim((string) ($this->config['print_dir'] ?? ''), '/') . '/' . $code,
            rtrim((string) ($this->config['hotfolder_dir'] ?? ''), '/') . '/' . $code,
        ];
        foreach ($candidates as $dir) {
            if ($dir !== '/' . $code && $dir !== DIRECTORY_SEPARATOR . $code && is_dir($dir)) {
                return $dir;
            }
        }

        return '';
    }
}
