<?php

namespace App\Services\MicrosoftGraph;

use App\Models\MsgraphModelChange;
use Illuminate\Support\Facades\Log;

/**
 * Service for tracking committee and workgroup model changes
 */
class MsgraphModelChangeService
{
    /**
     * Track when a model is created
     */
    public function trackModelCreated($model, array $metadata = []): void
    {
        $this->createModelChange(
            $model,
            'model_created',
            null, // no old status
            $this->getModelStatus($model),
            null, // no old title
            $this->getModelTitle($model),
            $metadata
        );

        $modelType = class_basename($model);
        Log::info("📝 {$modelType} created - Microsoft Graph sync pending", [
            'model_id' => $model->id,
            'model_title' => $this->getModelTitle($model),
            'model_status' => $this->getModelStatus($model),
        ]);
    }

    /**
     * Track when a model is deleted
     */
    public function trackModelDeleted($model, array $metadata = []): void
    {
        $this->createModelChange(
            $model,
            'model_deleted',
            $this->getModelStatus($model),
            null, // no new status
            $this->getModelTitle($model),
            null, // no new title
            $metadata
        );

        $modelType = class_basename($model);
        Log::info("📝 {$modelType} deleted - Microsoft Graph sync pending", [
            'model_id' => $model->id,
            'model_title' => $this->getModelTitle($model),
            'old_status' => $this->getModelStatus($model),
        ]);
    }

    /**
     * Track when a model's status changes
     */
    public function trackStatusChanged($model, string $oldStatus, string $newStatus, array $metadata = []): void
    {
        // Only track if status actually changed
        if ($oldStatus === $newStatus) {
            return;
        }

        $this->createModelChange(
            $model,
            'status_changed',
            $oldStatus,
            $newStatus,
            null, // no title change
            null, // no title change
            array_merge($metadata, [
                'model_title' => $this->getModelTitle($model)
            ])
        );

        $modelType = class_basename($model);
        Log::info("📝 {$modelType} status changed - Microsoft Graph sync pending", [
            'model_id' => $model->id,
            'model_title' => $this->getModelTitle($model),
            'old_status' => $oldStatus,
            'new_status' => $newStatus,
        ]);
    }

    /**
     * Track when a model's title changes
     */
    public function trackTitleChanged($model, string $oldTitle, string $newTitle, string $language = 'en', array $metadata = []): void
    {
        // Only track if title actually changed
        if ($oldTitle === $newTitle) {
            return;
        }

        $this->createModelChange(
            $model,
            'title_changed',
            null, // no status change
            null, // no status change
            $oldTitle,
            $newTitle,
            array_merge($metadata, [
                'language' => $language,
                'model_status' => $this->getModelStatus($model)
            ]),
            $language
        );

        $modelType = class_basename($model);
        Log::info("📝 {$modelType} title changed - Microsoft Graph sync pending", [
            'model_id' => $model->id,
            'old_title' => $oldTitle,
            'new_title' => $newTitle,
            'language' => $language,
            'model_status' => $this->getModelStatus($model),
        ]);
    }

    /**
     * Get all unprocessed model changes ordered by priority
     */
    public function getAllPendingModelChanges()
    {
        return MsgraphModelChange::unprocessed()
            ->orderByRaw("FIELD(priority, 'high', 'normal', 'low')")
            ->orderBy('created_at')
            ->get();
    }

    /**
     * Get pending changes for a specific model
     */
    public function getPendingModelChangesForModel($model)
    {
        return MsgraphModelChange::unprocessed()
            ->forModel($model)
            ->orderByRaw("FIELD(priority, 'high', 'normal', 'low')")
            ->orderBy('created_at')
            ->get();
    }

    /**
     * Mark model changes as processed for a specific model
     */
    public function markModelChangesAsProcessed($model): int
    {
        return MsgraphModelChange::unprocessed()
            ->forModel($model)
            ->update([
                'processed' => true,
                'processed_at' => now()
            ]);
    }

    /**
     * Mark specific model changes as processed
     */
    public function markSpecificModelChangesAsProcessed(array $changeIds): int
    {
        return MsgraphModelChange::whereIn('id', $changeIds)
            ->where('processed', false)
            ->update([
                'processed' => true,
                'processed_at' => now()
            ]);
    }

    /**
     * Create a model change record
     */
    private function createModelChange(
        $model,
        string $action,
        string $oldStatus = null,
        string $newStatus = null,
        string $oldTitle = null,
        string $newTitle = null,
        array $metadata = [],
        string $language = null
    ): MsgraphModelChange {
        return MsgraphModelChange::create([
            'model_type' => get_class($model),
            'model_id' => $model->id,
            'action' => $action,
            'old_status' => $oldStatus,
            'new_status' => $newStatus,
            'old_title' => $oldTitle,
            'new_title' => $newTitle,
            'language' => $language,
            'metadata' => $metadata,
            'priority' => $this->determinePriority($action, $oldStatus, $newStatus),
        ]);
    }

    /**
     * Get the status of a model (from website_object)
     */
    private function getModelStatus($model): ?string
    {
        if (method_exists($model, 'website_object') && $model->website_object) {
            return $model->website_object->status;
        }

        // Fallback check for published status
        return $model->status ?? null;
    }

    /**
     * Get the title of a model (from language tables)
     */
    private function getModelTitle($model): ?string
    {
        // Try to get title from the model directly (if it has a title attribute)
        if (isset($model->title)) {
            return $model->title;
        }

        // Try to get title from language relationship
        if (method_exists($model, 'languages') && $model->languages) {
            $firstLanguage = $model->languages->first();
            return $firstLanguage ? $firstLanguage->title : null;
        }

        return null;
    }

    /**
     * Determine priority based on action and status changes
     */
    private function determinePriority(string $action, ?string $oldStatus, ?string $newStatus): string
    {
        // High priority for deletions and status changes to/from published
        if ($action === 'model_deleted') {
            return 'high';
        }

        if ($action === 'status_changed') {
            if ($oldStatus === 'published' || $newStatus === 'published') {
                return 'high';
            }
        }

        // Normal priority for everything else
        return 'normal';
    }
}
