<?php

namespace App\Models;

use App\Core\Database;

/**
 * SallaMerchant Model
 * Handles database representation of Salla e-commerce store links per company.
 */
class SallaMerchant extends BaseModel
{
    protected static string $table = 'salla_merchants';

    /**
     * Find merchant info by company ID
     */
    public static function findByCompany(int $companyId): ?array
    {
        self::ensureTableExists();
        return Database::selectOne(
            "SELECT * FROM " . static::$table . " WHERE company_id = ? LIMIT 1",
            [$companyId]
        );
    }

    /**
     * Find merchant info by Salla merchant ID
     */
    public static function findByMerchantId(string $merchantId): ?array
    {
        self::ensureTableExists();
        return Database::selectOne(
            "SELECT * FROM " . static::$table . " WHERE merchant_id = ? LIMIT 1",
            [$merchantId]
        );
    }

    /**
     * Save or update Salla merchant credentials
     */
    public static function saveSecure(array $data): string
    {
        self::ensureTableExists();
        
        $existing = self::findByCompany($data['company_id']);
        if ($existing) {
            self::update($existing['id'], $data);
            return $existing['id'];
        } else {
            return self::create($data);
        }
    }

    /**
     * Delete credentials for a company
     */
    public static function deleteByCompany(int $companyId): int
    {
        self::ensureTableExists();
        return Database::execute(
            "DELETE FROM " . static::$table . " WHERE company_id = ?",
            [$companyId]
        );
    }

    /**
     * Get or dynamically refresh the access token for a company
     */
    public static function getOrRefreshAccessToken(int $companyId): ?string
    {
        $merchant = self::findByCompany($companyId);
        if (!$merchant) {
            return null;
        }

        // Check if token expires_at is in the future (> 5 mins remaining)
        $expiresAt = strtotime($merchant['expires_at']);
        if ($expiresAt && ($expiresAt - time()) > 300) {
            return $merchant['access_token'];
        }

        // Token expired or close to it, refresh
        $clientId = getenv('SALLA_CLIENT_ID') ?: '69ea789c-f611-4ea7-a3ee-7ead41420225';
        $clientSecret = getenv('SALLA_CLIENT_SECRET') ?: '';

        $ch = curl_init('https://accounts.salla.sa/oauth2/token');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
            'client_id' => $clientId,
            'client_secret' => $clientSecret,
            'grant_type' => 'refresh_token',
            'refresh_token' => $merchant['refresh_token']
        ]));
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/x-www-form-urlencoded'
        ]);
        curl_setopt($ch, CURLOPT_TIMEOUT, 15);
        
        $res = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode !== 200) {
            error_log("Failed to refresh Salla token for company $companyId. Response: $res");
            return null;
        }

        $tokenData = json_decode($res, true);
        if (empty($tokenData['access_token'])) {
            return null;
        }

        $accessToken = $tokenData['access_token'];
        $refreshToken = $tokenData['refresh_token'] ?? $merchant['refresh_token'];
        $expiresIn = $tokenData['expires_in'] ?? 2592000;
        $newExpiresAt = date('Y-m-d H:i:s', time() + $expiresIn);

        self::saveSecure([
            'company_id' => $companyId,
            'merchant_id' => $merchant['merchant_id'],
            'store_name' => $merchant['store_name'],
            'access_token' => $accessToken,
            'refresh_token' => $refreshToken,
            'expires_at' => $newExpiresAt
        ]);

        return $accessToken;
    }


    /**
     * Ensure the salla_merchants table exists
     */
    public static function ensureTableExists(): void
    {
        static $checked = false;
        if ($checked) return;

        try {
            Database::execute("
                CREATE TABLE IF NOT EXISTS `salla_merchants` (
                    `id` INT AUTO_INCREMENT PRIMARY KEY,
                    `company_id` INT NOT NULL,
                    `merchant_id` VARCHAR(100) NOT NULL UNIQUE,
                    `store_name` VARCHAR(255) NULL,
                    `access_token` TEXT NOT NULL,
                    `refresh_token` TEXT NOT NULL,
                    `expires_at` TIMESTAMP NULL DEFAULT NULL,
                    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                    FOREIGN KEY (`company_id`) REFERENCES `companies`(`id`) ON DELETE CASCADE
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
            ");
            $checked = true;
        } catch (\Exception $e) {
            error_log("Failed to ensure salla_merchants table: " . $e->getMessage());
        }
    }
}
