<?php

require_once APP_ROOT . '/helpers/NumistaAPI.php';

class ApiController
{
    private function downloadNumistaImage(?string $imageUrl, string $prefix): ?string
    {
        if (empty($imageUrl)) {
            return null;
        }

        // Check if this is a large image and if large image download is disabled
        if (strpos($imageUrl, '-original.') !== false) {
            $settingModel = new Setting();
            $downloadLargeImages = $settingModel->get('download_numista_large_images') ?? '0';
            if ($downloadLargeImages !== '1') {
                // Skip downloading large images if setting is disabled
                return null;
            }
        }

        try {
            // Use cURL for image download
            $ch = curl_init($imageUrl);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'Accept: image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8',
                'Accept-Language: en-US,en;q=0.9',
                'Accept-Encoding: gzip, deflate, br',
                'DNT: 1',
                'Connection: keep-alive',
                'Upgrade-Insecure-Requests: 1',
                'Sec-Fetch-Dest: image',
                'Sec-Fetch-Mode: no-cors',
                'Sec-Fetch-Site: cross-site',
                'Referer: https://notaphily-catalogue.com'
            ]);
            curl_setopt($ch, CURLOPT_REFERER, 'https://notaphily-catalogue.com');
            
            $imageData = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $error = curl_error($ch);
            curl_close($ch);

            if ($imageData === false || !empty($error) || $httpCode !== 200) {
                return null;
            }

            $extension = 'jpg';
            if (preg_match('/\.(jpg|jpeg|png|gif|webp)$/i', $imageUrl, $matches)) {
                $extension = strtolower($matches[1]);
            }

            $filename = $prefix . '_' . uniqid() . '.' . $extension;
            $filepath = UPLOAD_ITEMS_PATH . '/' . $filename;

            // Create directory if it doesn't exist
            if (!is_dir(UPLOAD_ITEMS_PATH)) {
                mkdir(UPLOAD_ITEMS_PATH, 0755, true);
            }

            if (file_put_contents($filepath, $imageData) === false) {
                return null;
            }

            // Verify file was created and has content
            if (!file_exists($filepath) || filesize($filepath) === 0) {
                return null;
            }

            return $filename;
        } catch (Exception $e) {
            error_log("Failed to download Numista image: " . $e->getMessage());
            return null;
        }
    }

    private function formatDimensions($dimensions): string
    {
        if (is_string($dimensions)) {
            return $dimensions;
        }

        if (!is_array($dimensions)) {
            return '';
        }

        $width = $dimensions['width'] ?? $dimensions['length'] ?? null;
        $height = $dimensions['height'] ?? null;
        $unit = $dimensions['unit'] ?? 'mm';

        $extractValue = function ($value) {
            if (is_array($value)) {
                return $value['value'] ?? $value['text'] ?? null;
            }

            return $value;
        };

        $width = $extractValue($width);
        $height = $extractValue($height);

        if (is_array($unit)) {
            $unit = $unit['code'] ?? $unit['text'] ?? 'mm';
        }

        if ($width !== null && $height !== null) {
            return trim($width . ' x ' . $height . ' ' . $unit);
        }

        if ($width !== null) {
            return trim($width . ' ' . $unit);
        }

        if ($height !== null) {
            return trim($height . ' ' . $unit);
        }

        if (!empty($dimensions['text']) && is_string($dimensions['text'])) {
            return $dimensions['text'];
        }

        $numericValues = [];
        $collectNumericValues = function ($value) use (&$collectNumericValues, &$numericValues): void {
            if (is_array($value)) {
                foreach ($value as $nestedValue) {
                    $collectNumericValues($nestedValue);
                }
                return;
            }

            if (is_int($value) || is_float($value)) {
                $numericValues[] = $value;
                return;
            }

            if (is_string($value) && is_numeric($value)) {
                $numericValues[] = $value + 0;
            }
        };

        $collectNumericValues($dimensions);
        $numericValues = array_values(array_unique($numericValues, SORT_REGULAR));

        if (count($numericValues) >= 2) {
            return trim($numericValues[0] . ' x ' . $numericValues[1] . ' ' . $unit);
        }

        if (count($numericValues) === 1) {
            return trim($numericValues[0] . ' ' . $unit);
        }

        return '';
    }

    private function normalizeSearchResults(array $results, ?string $expectedCategory = null, ?int $expectedYear = null): array
    {
        $types = $results['types'] ?? $results;
        if (!is_array($types)) {
            return [];
        }

        $normalized = array_values(array_map(function ($type) {
            $issuer = is_array($type['issuer'] ?? null) ? $type['issuer'] : [];
            $value = is_array($type['value'] ?? null) ? $type['value'] : [];
            $category = is_array($type['category'] ?? null) ? ($type['category']['code'] ?? $type['category']['name'] ?? null) : ($type['category'] ?? null);

            return [
                'id' => (int)($type['id'] ?? 0),
                'title' => $type['title'] ?? $type['name'] ?? 'Nepoznato',
                'country' => $issuer['name'] ?? '',
                'year' => $type['min_year'] ?? $type['year'] ?? '',
                'value' => $value['text'] ?? $type['value'] ?? '',
                'min_date' => $type['min_year'] ?? $type['min_date'] ?? '',
                'max_date' => $type['max_year'] ?? $type['max_date'] ?? '',
                'category' => $category,
                'url' => $type['url'] ?? null,
                'obverse_thumbnail' => $type['obverse_thumbnail'] ?? null,
                'reverse_thumbnail' => $type['reverse_thumbnail'] ?? null,
            ];
        }, $types));

        if ($expectedCategory === null) {
            $filtered = $normalized;
        } else {
            $filtered = array_values(array_filter($normalized, function ($type) use ($expectedCategory) {
                return ($type['category'] ?? null) === $expectedCategory;
            }));
        }

        if ($expectedYear === null) {
            return $filtered;
        }

        return array_values(array_filter($filtered, function ($type) use ($expectedYear) {
            $minYear = isset($type['min_date']) && $type['min_date'] !== '' ? (int)$type['min_date'] : null;
            $maxYear = isset($type['max_date']) && $type['max_date'] !== '' ? (int)$type['max_date'] : null;
            $year = isset($type['year']) && $type['year'] !== '' ? (int)$type['year'] : null;

            if ($minYear !== null && $maxYear !== null) {
                return $expectedYear >= $minYear && $expectedYear <= $maxYear;
            }

            if ($year !== null) {
                return $year === $expectedYear;
            }

            return false;
        }));
    }

    private function formatDimensionsFromSize(array $details): string
    {
        $size = $details['size'] ?? null;
        $size2 = $details['size2'] ?? null;
        
        if ($size !== null && $size2 !== null) {
            return trim($size . ' x ' . $size2 . ' mm');
        }
        
        // Fallback to old method if size/size2 not available
        return $this->extractDimensionsFromDetails($details);
    }

    private function extractDimensionsFromDetails(array $details): string
    {
        $candidates = [
            $details['size'] ?? null,
            $details['dimensions'] ?? null,
            [
                'width' => $details['size_2'] ?? $details['secondary_size'] ?? $details['size_secondary'] ?? null,
                'height' => $details['size_1'] ?? $details['primary_size'] ?? $details['main_size'] ?? null,
                'length' => $details['length'] ?? null,
                'unit' => $details['unit'] ?? $details['size_unit'] ?? 'mm',
            ],
            [
                'width' => $details['width'] ?? $details['size_width'] ?? null,
                'height' => $details['height'] ?? $details['size_height'] ?? null,
                'length' => $details['length'] ?? $details['size_length'] ?? null,
                'unit' => $details['unit'] ?? $details['size_unit'] ?? 'mm',
            ],
        ];

        foreach ($candidates as $candidate) {
            $formatted = $this->formatDimensions($candidate);
            if ($formatted !== '') {
                return $formatted;
            }
        }

        return '';
    }

    private function normalizeDetails(array $details, array $pricing = []): array
    {
        $issuer = is_array($details['issuer'] ?? null) ? $details['issuer'] : [];
        $value = is_array($details['value'] ?? null) ? $details['value'] : [];
        $composition = is_array($details['composition'] ?? null) ? $details['composition'] : [];
        $obverse = is_array($details['obverse'] ?? null) ? $details['obverse'] : [];
        $reverse = is_array($details['reverse'] ?? null) ? $details['reverse'] : [];
        $colors = $details['colors'] ?? $details['color'] ?? '';
        $orientation = $details['orientation'] ?? '';

        if (is_array($orientation)) {
            $orientation = $orientation['text'] ?? '';
        }

        $colorText = '';
        if (is_array($colors)) {
            $colorNames = array_map(function ($color) {
                if (is_array($color)) {
                    return $color['name'] ?? $color['text'] ?? null;
                }

                return is_string($color) ? $color : null;
            }, $colors);

            $colorNames = array_values(array_filter($colorNames));
            $colorText = implode(', ', $colorNames);
        } elseif (is_string($colors)) {
            $colorText = $colors;
        }

        $orientationValue = '';
        if (is_string($orientation) && $orientation !== '') {
            $orientationLower = strtolower($orientation);
            if (str_contains($orientationLower, 'medal')) {
                $orientationValue = 'medal';
            } elseif (str_contains($orientationLower, 'coin')) {
                $orientationValue = 'coin';
            }
        }

        $normalized = [
            'id' => (int)($details['id'] ?? 0),
            'url' => $details['url'] ?? null,
            'title' => $details['title'] ?? '',
            'country' => $issuer['name'] ?? '',
            'value' => $value['text'] ?? $details['value'] ?? '',
            'year' => $details['min_year'] ?? $details['year'] ?? '',
            'min_date' => $details['min_year'] ?? $details['min_date'] ?? '',
            'max_date' => $details['max_year'] ?? $details['max_date'] ?? '',
            'catalog_number' => $details['numista_number'] ?? $details['id'] ?? null,
            'composition' => $composition['text'] ?? $details['composition'] ?? '',
            'weight' => $details['weight'] ?? null,
            'diameter' => $details['diameter'] ?? null,
            'thickness' => $details['thickness'] ?? null,
            'orientation' => $orientationValue,
            'mintage' => $details['mintage'] ?? null,
            'dimensions' => $this->formatDimensionsFromSize($details),
            'color' => $colorText,
            'obverse_description' => $obverse['description'] ?? $details['obverse_description'] ?? '',
            'reverse_description' => $reverse['description'] ?? $details['reverse_description'] ?? '',
            'pricing' => $pricing,
            'obverse_thumbnail' => $obverse['thumbnail'] ?? $details['obverse_thumbnail'] ?? null,
            'reverse_thumbnail' => $reverse['thumbnail'] ?? $details['reverse_thumbnail'] ?? null,
            'obverse_picture' => $obverse['picture'] ?? null,
            'reverse_picture' => $reverse['picture'] ?? null,
        ];

        if (!empty($obverse['lettering']) || !empty($reverse['lettering'])) {
            $normalized['legends'] = trim(implode(' / ', array_filter([
                $obverse['lettering'] ?? '',
                $reverse['lettering'] ?? '',
            ])));
        }

        return $normalized;
    }

    public function searchNumista(): void
    {
        header('Content-Type: application/json');

        if (!Session::isLoggedIn()) {
            http_response_code(401);
            echo json_encode(['error' => 'Unauthorized']);
            exit;
        }

        $type = $_GET['type'] ?? 'coin';
        $requestedYear = isset($_GET['year']) && trim((string)$_GET['year']) !== '' ? (int)$_GET['year'] : null;

        try {
            $api = new NumistaAPI();
            $filters = [
                'issuer' => $_GET['country'] ?? '', // Map country to issuer
                'year' => $_GET['year'] ?? '',
                'value' => $_GET['value'] ?? '',
            ];

            // Remove empty filters
            $filters = array_filter($filters, function($value) {
                return !empty($value);
            });

            if ($type === 'banknote') {
                $results = $api->searchBanknotes($filters);
            } else {
                $results = $api->searchCoins($filters);
            }

            echo json_encode([
                'success' => true,
                'results' => $this->normalizeSearchResults($results, $type, $requestedYear),
                'raw' => $results,
            ]);
        } catch (Exception $e) {
            http_response_code(500);
            echo json_encode(['error' => $e->getMessage()]);
        }
    }

    public function getCoinDetails($numista_id = null): void
    {
        header('Content-Type: application/json');

        if (!Session::isLoggedIn()) {
            http_response_code(401);
            echo json_encode(['error' => 'Unauthorized']);
            exit;
        }

        $numistaId = (int)($numista_id ?? $_GET['numista_id'] ?? 0);

        if ($numistaId === 0) {
            http_response_code(400);
            echo json_encode(['error' => 'Invalid Numista ID']);
            exit;
        }

        try {
            $api = new NumistaAPI();
            $details = $api->getCoinDetails($numistaId);

            // Get pricing data
            $pricing = [];
            try {
                $pricing = $api->getPricing($numistaId);
            } catch (Exception $e) {
                // Pricing might not be available, continue without it
            }

            // Get literature references from details
            $literature = $details['references'] ?? [];

            $normalized = $this->normalizeDetails($details, $pricing);

            // Download Numista large format images to local server
            $downloadedObverse = null;
            $downloadedReverse = null;

            if (!empty($normalized['obverse_picture'])) {
                $downloadedObverse = $this->downloadNumistaImage($normalized['obverse_picture'], 'numista_obverse');
            } elseif (!empty($normalized['obverse_thumbnail'])) {
                $downloadedObverse = $this->downloadNumistaImage($normalized['obverse_thumbnail'], 'numista_obverse');
            }
            if (!empty($normalized['reverse_picture'])) {
                $downloadedReverse = $this->downloadNumistaImage($normalized['reverse_picture'], 'numista_reverse');
            } elseif (!empty($normalized['reverse_thumbnail'])) {
                $downloadedReverse = $this->downloadNumistaImage($normalized['reverse_thumbnail'], 'numista_reverse');
            }

            echo json_encode([
                'success' => true,
                'details' => $normalized,
                'pricing' => $pricing,
                'literature' => $literature,
                'downloaded_images' => [
                    'obverse' => $downloadedObverse,
                    'reverse' => $downloadedReverse,
                ],
            ]);
        } catch (Exception $e) {
            http_response_code(500);
            echo json_encode(['error' => $e->getMessage()]);
        }
    }

    public function getBanknoteDetails($numista_id = null): void
    {
        header('Content-Type: application/json');

        if (!Session::isLoggedIn()) {
            http_response_code(401);
            echo json_encode(['error' => 'Unauthorized']);
            exit;
        }

        $numistaId = (int)($numista_id ?? $_GET['numista_id'] ?? 0);

        if ($numistaId === 0) {
            http_response_code(400);
            echo json_encode(['error' => 'Invalid Numista ID']);
            exit;
        }

        try {
            $api = new NumistaAPI();
            $details = $api->getBanknoteDetails($numistaId);
            
            
            // Get literature references from details
            $literature = $details['references'] ?? [];

            $normalized = $this->normalizeDetails($details);

            // Download Numista large format images to local server
            $downloadedObverse = null;
            $downloadedReverse = null;

            if (!empty($normalized['obverse_picture'])) {
                $downloadedObverse = $this->downloadNumistaImage($normalized['obverse_picture'], 'numista_obverse');
            } elseif (!empty($normalized['obverse_thumbnail'])) {
                $downloadedObverse = $this->downloadNumistaImage($normalized['obverse_thumbnail'], 'numista_obverse');
            }
            if (!empty($normalized['reverse_picture'])) {
                $downloadedReverse = $this->downloadNumistaImage($normalized['reverse_picture'], 'numista_reverse');
            } elseif (!empty($normalized['reverse_thumbnail'])) {
                $downloadedReverse = $this->downloadNumistaImage($normalized['reverse_thumbnail'], 'numista_reverse');
            }

            echo json_encode([
                'success' => true,
                'details' => $normalized,
                'literature' => $literature,
                'downloaded_images' => [
                    'obverse' => $downloadedObverse,
                    'reverse' => $downloadedReverse,
                ],
            ]);
        } catch (Exception $e) {
            http_response_code(500);
            echo json_encode(['error' => $e->getMessage()]);
        }
    }

    public function getIssuers(): void
    {
        header('Content-Type: application/json');

        if (!Session::isLoggedIn()) {
            http_response_code(401);
            echo json_encode(['error' => 'Unauthorized']);
            exit;
        }

        try {
            $api = new NumistaAPI();
            $issuers = $api->getIssuers();

            echo json_encode(['success' => true, 'issuers' => $issuers]);
        } catch (Exception $e) {
            http_response_code(500);
            echo json_encode(['error' => $e->getMessage()]);
        }
    }
}
