<?php

namespace App\Services;

use App\Models\LocalizedContent;
use App\Models\LocalizationCache;
use App\Models\LocalizationAuditLog;
use App\Models\Brand;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Exception;

class LocalizationService
{
    protected AITranslationService $translationService;

    public function __construct(AITranslationService $translationService)
    {
        $this->translationService = $translationService;
    }

    /**
     * Request localization for content.
     *
     * @param int $brandId Brand ID
     * @param string $contentType Type of content (ad, post, proposal, campaign)
     * @param int $contentId ID of the content
     * @param string $sourceText Original text to translate
     * @param array $targetLocales Array of target locale codes
     * @param string $tone Translation tone (formal, friendly, neutral)
     * @param User $user User requesting the localization
     * @param string|null $context Additional context
     * @return array Array of created LocalizedContent instances
     * @throws Exception
     */
    public function requestLocalization(
        int $brandId,
        string $contentType,
        int $contentId,
        string $sourceText,
        array $targetLocales,
        string $tone,
        User $user,
        ?string $context = null
    ): array {
        $results = [];
        $sourceLocale = 'en'; // Default source locale

        DB::beginTransaction();
        try {
            foreach ($targetLocales as $targetLocale) {
                // Check if localization already exists
                $existing = LocalizedContent::where('content_type', $contentType)
                    ->where('content_id', $contentId)
                    ->where('locale_code', $targetLocale)
                    ->first();

                if ($existing) {
                    $results[] = [
                        'locale' => $targetLocale,
                        'status' => 'exists',
                        'localized_content' => $existing,
                    ];
                    continue;
                }

                // Check cache first
                $cached = $this->getCachedTranslation($sourceText, $sourceLocale, $targetLocale, $tone);

                if ($cached) {
                    // Use cached translation
                    $localizedContent = $this->createLocalizedContent(
                        $brandId,
                        $contentType,
                        $contentId,
                        $sourceText,
                        $targetLocale,
                        $cached['translated_text'],
                        $cached['cultural_notes'],
                        $tone,
                        $cached['job_id'] ?? 'cached',
                        $user
                    );

                    $results[] = [
                        'locale' => $targetLocale,
                        'status' => 'cached',
                        'localized_content' => $localizedContent,
                    ];
                } else {
                    // Generate new translation
                    $translation = $this->translationService->translate(
                        $sourceText,
                        $sourceLocale,
                        $targetLocale,
                        $tone,
                        $context
                    );

                    // Cache the translation
                    $this->cacheTranslation(
                        $sourceText,
                        $sourceLocale,
                        $targetLocale,
                        $tone,
                        $translation['translated_text'],
                        $translation['cultural_notes']
                    );

                    // Create localized content
                    $localizedContent = $this->createLocalizedContent(
                        $brandId,
                        $contentType,
                        $contentId,
                        $sourceText,
                        $targetLocale,
                        $translation['translated_text'],
                        $translation['cultural_notes'],
                        $tone,
                        $translation['job_id'],
                        $user
                    );

                    $results[] = [
                        'locale' => $targetLocale,
                        'status' => 'generated',
                        'localized_content' => $localizedContent,
                    ];
                }
            }

            DB::commit();
            return $results;

        } catch (Exception $e) {
            DB::rollBack();
            Log::error('Localization request failed', [
                'brand_id' => $brandId,
                'content_type' => $contentType,
                'content_id' => $contentId,
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }

    /**
     * Create localized content record.
     */
    protected function createLocalizedContent(
        int $brandId,
        string $contentType,
        int $contentId,
        string $sourceText,
        string $localeCode,
        string $localizedText,
        ?string $culturalNotes,
        string $tone,
        string $aiJobId,
        User $user
    ): LocalizedContent {
        $localizedContent = LocalizedContent::create([
            'brand_id' => $brandId,
            'content_type' => $contentType,
            'content_id' => $contentId,
            'locale_code' => $localeCode,
            'source_text' => $sourceText,
            'localized_text' => $localizedText,
            'cultural_notes' => $culturalNotes,
            'tone' => $tone,
            'ai_job_id' => $aiJobId,
            'status' => 'generated',
            'created_by' => $user->id,
        ]);

        // Log the creation
        LocalizationAuditLog::log(
            $localizedContent->id,
            $user->id,
            'created',
            null,
            $localizedText,
            "Localization created for {$localeCode}"
        );

        return $localizedContent;
    }

    /**
     * Get cached translation if available.
     */
    protected function getCachedTranslation(
        string $sourceText,
        string $sourceLocale,
        string $targetLocale,
        string $tone
    ): ?array {
        $cached = LocalizationCache::findCached($sourceText, $sourceLocale, $targetLocale, $tone);

        if ($cached) {
            $cached->incrementUsage();
            
            return [
                'translated_text' => $cached->translated_text,
                'cultural_notes' => $cached->cultural_notes,
                'job_id' => 'cached_' . $cached->id,
            ];
        }

        return null;
    }

    /**
     * Cache a translation.
     */
    protected function cacheTranslation(
        string $sourceText,
        string $sourceLocale,
        string $targetLocale,
        string $tone,
        string $translatedText,
        ?string $culturalNotes
    ): LocalizationCache {
        $hash = LocalizationCache::generateHash($sourceText, $sourceLocale, $targetLocale, $tone);

        return LocalizationCache::create([
            'source_text_hash' => $hash,
            'source_locale' => $sourceLocale,
            'target_locale' => $targetLocale,
            'tone' => $tone,
            'source_text' => $sourceText,
            'translated_text' => $translatedText,
            'cultural_notes' => $culturalNotes,
            'ai_provider' => 'openai',
            'usage_count' => 1,
            'last_used_at' => now(),
        ]);
    }

    /**
     * Approve localized content.
     */
    public function approveLocalization(LocalizedContent $localizedContent, User $user): LocalizedContent
    {
        $oldStatus = $localizedContent->status;
        $localizedContent->approve($user);

        // Log the approval
        LocalizationAuditLog::log(
            $localizedContent->id,
            $user->id,
            'approved',
            $oldStatus,
            'approved',
            "Localization approved by {$user->name}"
        );

        return $localizedContent;
    }

    /**
     * Reject localized content.
     */
    public function rejectLocalization(LocalizedContent $localizedContent, User $user, ?string $reason = null): LocalizedContent
    {
        $oldStatus = $localizedContent->status;
        $localizedContent->reject();

        // Log the rejection
        LocalizationAuditLog::log(
            $localizedContent->id,
            $user->id,
            'rejected',
            $oldStatus,
            'rejected',
            $reason ?? "Localization rejected by {$user->name}"
        );

        return $localizedContent;
    }

    /**
     * Edit localized content manually.
     */
    public function editLocalization(
        LocalizedContent $localizedContent,
        string $newText,
        User $user,
        ?string $notes = null
    ): LocalizedContent {
        $oldText = $localizedContent->localized_text;
        
        $localizedContent->localized_text = $newText;
        $localizedContent->markAsEdited();

        // Log the edit
        LocalizationAuditLog::log(
            $localizedContent->id,
            $user->id,
            'edited',
            $oldText,
            $newText,
            $notes ?? "Localization manually edited by {$user->name}"
        );

        return $localizedContent;
    }

    /**
     * Export localized content.
     */
    public function exportLocalization(LocalizedContent $localizedContent, User $user): array
    {
        // Log the export
        LocalizationAuditLog::log(
            $localizedContent->id,
            $user->id,
            'exported',
            null,
            null,
            "Localization exported by {$user->name}"
        );

        return [
            'locale_code' => $localizedContent->locale_code,
            'locale_name' => $localizedContent->locale_display_name,
            'source_text' => $localizedContent->source_text,
            'localized_text' => $localizedContent->localized_text,
            'cultural_notes' => $localizedContent->cultural_notes,
            'tone' => $localizedContent->tone,
            'status' => $localizedContent->status,
            'created_at' => $localizedContent->created_at->toIso8601String(),
            'approved_at' => $localizedContent->approved_at?->toIso8601String(),
        ];
    }

    /**
     * Get all localizations for content.
     */
    public function getContentLocalizations(string $contentType, int $contentId): array
    {
        return LocalizedContent::where('content_type', $contentType)
            ->where('content_id', $contentId)
            ->with(['creator', 'approver'])
            ->orderBy('locale_code')
            ->get()
            ->toArray();
    }

    /**
     * Get localization statistics for a brand.
     */
    public function getBrandLocalizationStats(int $brandId): array
    {
        $total = LocalizedContent::where('brand_id', $brandId)->count();
        $approved = LocalizedContent::where('brand_id', $brandId)->where('status', 'approved')->count();
        $pending = LocalizedContent::where('brand_id', $brandId)->where('status', 'generated')->count();
        $rejected = LocalizedContent::where('brand_id', $brandId)->where('status', 'rejected')->count();

        $byLocale = LocalizedContent::where('brand_id', $brandId)
            ->select('locale_code', DB::raw('count(*) as count'))
            ->groupBy('locale_code')
            ->get()
            ->pluck('count', 'locale_code')
            ->toArray();

        return [
            'total' => $total,
            'approved' => $approved,
            'pending' => $pending,
            'rejected' => $rejected,
            'by_locale' => $byLocale,
        ];
    }
}