<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class QadSyncLog extends Model
{
    use HasFactory;

    protected $table = 't_qad_sync_logs';

    protected $fillable = [
        'sync_type',
        'status',
        'total_from_qad',
        'total_inserted',
        'total_updated',
        'total_errors',
        'error_details',
        'sync_details',
        'started_at',
        'completed_at',
        'duration_seconds',
        'triggered_by',
        'trigger_type',
        'qad_response_time',
        'request_details',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'started_at' => 'datetime',
        'completed_at' => 'datetime',
        'error_details' => 'array',
        'sync_details' => 'array',
        'request_details' => 'array',
        'total_from_qad' => 'integer',
        'total_inserted' => 'integer',
        'total_updated' => 'integer',
        'total_errors' => 'integer',
        'duration_seconds' => 'decimal:6',
        'qad_response_time' => 'decimal:6',
    ];

    // Status constants
    const STATUS_RUNNING = 'Running';
    const STATUS_SUCCESS = 'Success';
    const STATUS_FAILED = 'Failed';
    const STATUS_PARTIAL = 'Partial';

    // Sync type constants
    const TYPE_STORES = 'stores';
    const TYPE_MENUS = 'menus';
    const TYPE_ALL = 'all';

    // Trigger type constants
    const TRIGGER_MANUAL = 'manual';
    const TRIGGER_SCHEDULED = 'scheduled';
    const TRIGGER_API = 'api';

    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    public function modificator()
    {
        return $this->belongsTo(User::class, 'updated_by');
    }

    public function triggeredBy()
    {
        return $this->belongsTo(User::class, 'triggered_by');
    }

    // Create new sync log entry
    public static function startSync($syncType, $triggerType = self::TRIGGER_MANUAL, $triggeredBy = null)
    {
        return static::create([
            'sync_type' => $syncType,
            'status' => self::STATUS_RUNNING,
            'started_at' => now(),
            'trigger_type' => $triggerType,
            'triggered_by' => $triggeredBy ?? auth()->id(),
            'created_by' => auth()->id() ?? 1,
        ]);
    }

    // Complete sync log
    public function completeSync($result, $qadResponseTime = null, $requestDetails = null)
    {
        $status = $this->determineSyncStatus($result);
        
        $updateData = [
            'status' => $status,
            'completed_at' => now(),
            'duration_seconds' => now()->diffInSeconds($this->started_at),
            'qad_response_time' => $qadResponseTime,
            'total_from_qad' => $this->extractTotalFromQad($result),
            'total_inserted' => $this->extractTotalInserted($result),
            'total_updated' => $this->extractTotalUpdated($result),
            'total_errors' => $this->extractTotalErrors($result),
            'error_details' => $this->extractErrorDetails($result),
            'sync_details' => $this->extractSyncDetails($result),
            'updated_by' => auth()->id() ?? 1,
        ];
        
        if ($requestDetails !== null) {
            $updateData['request_details'] = $requestDetails;
        }
        
        $this->update($updateData);
    }

    // Determine sync status based on result
    private function determineSyncStatus($result)
    {
        if (!$result || !isset($result['success'])) {
            return self::STATUS_FAILED;
        }

        if (!$result['success']) {
            return self::STATUS_FAILED;
        }

        $totalErrors = $this->extractTotalErrors($result);
        if ($totalErrors > 0) {
            return self::STATUS_PARTIAL;
        }

        return self::STATUS_SUCCESS;
    }

    // Extract total from QAD
    private function extractTotalFromQad($result)
    {
        if (isset($result['total_from_qad'])) {
            return $result['total_from_qad'];
        }

        if (isset($result['stores']) && isset($result['menus'])) {
            return ($result['stores']['total_from_qad'] ?? 0) + ($result['menus']['total_from_qad'] ?? 0);
        }

        return 0;
    }

    // Extract total inserted
    private function extractTotalInserted($result)
    {
        if (isset($result['inserted'])) {
            return $result['inserted'];
        }

        if (isset($result['summary']['total_inserted'])) {
            return $result['summary']['total_inserted'];
        }

        return 0;
    }

    // Extract total updated
    private function extractTotalUpdated($result)
    {
        if (isset($result['updated'])) {
            return $result['updated'];
        }

        if (isset($result['summary']['total_updated'])) {
            return $result['summary']['total_updated'];
        }

        return 0;
    }

    // Extract total errors
    private function extractTotalErrors($result)
    {
        if (isset($result['errors'])) {
            return count($result['errors']);
        }

        if (isset($result['summary']['total_errors'])) {
            return $result['summary']['total_errors'];
        }

        return 0;
    }

    // Extract error details
    private function extractErrorDetails($result)
    {
        $errors = [];

        if (isset($result['errors']) && is_array($result['errors'])) {
            $errors = array_merge($errors, $result['errors']);
        }

        if (isset($result['stores']['errors']) && is_array($result['stores']['errors'])) {
            $errors = array_merge($errors, array_map(function($error) {
                return ['type' => 'stores', 'error' => $error];
            }, $result['stores']['errors']));
        }

        if (isset($result['menus']['errors']) && is_array($result['menus']['errors'])) {
            $errors = array_merge($errors, array_map(function($error) {
                return ['type' => 'menus', 'error' => $error];
            }, $result['menus']['errors']));
        }

        return $errors;
    }

    // Extract sync details
    private function extractSyncDetails($result)
    {
        $details = [];

        if (isset($result['details'])) {
            $details = $result['details'];
        }

        if (isset($result['stores']['details'])) {
            $details['stores'] = $result['stores']['details'];
        }

        if (isset($result['menus']['details'])) {
            $details['menus'] = $result['menus']['details'];
        }

        return $details;
    }

    // Get recent sync logs
    public static function getRecentLogs($limit = 50)
    {
        return static::with(['creator', 'triggeredBy'])
            ->orderBy('started_at', 'desc')
            ->limit($limit)
            ->get();
    }

    // Get sync statistics
    public static function getSyncStatistics($days = 30)
    {
        $startDate = now()->subDays($days);
        
        return [
            'total_syncs' => static::where('started_at', '>=', $startDate)->count(),
            'successful_syncs' => static::where('started_at', '>=', $startDate)
                ->where('status', self::STATUS_SUCCESS)->count(),
            'failed_syncs' => static::where('started_at', '>=', $startDate)
                ->where('status', self::STATUS_FAILED)->count(),
            'partial_syncs' => static::where('started_at', '>=', $startDate)
                ->where('status', self::STATUS_PARTIAL)->count(),
            'avg_duration' => static::where('started_at', '>=', $startDate)
                ->where('status', '!=', self::STATUS_RUNNING)
                ->avg('duration_seconds'),
            'total_records_synced' => static::where('started_at', '>=', $startDate)
                ->sum(\DB::raw('total_inserted + total_updated')),
        ];
    }

    // Cleanup old logs
    public static function cleanupOldLogs($keepDays = 90)
    {
        $cutoffDate = now()->subDays($keepDays);
        return static::where('started_at', '<', $cutoffDate)->delete();
    }
}