<?php

namespace App\Http\Livewire;

use Livewire\Component;
use Carbon\Carbon;
use DateTimeZone;
use Illuminate\Support\Facades\Log;

class Dashboard extends Component
{
    // Existing properties
    public $totMembers = 0;
    public $totSuppliers = 0;
    public $totTodayIn = 0;
    public $totTodayOut = 0;
    public $dayName;
    public $in;
    public $out;
    public $members;
    public $activeUsers = 0;
    public $registeredUsers = 0;
    public $expiredCertificates = 0;
    public $suspendedSubscriptions = 0;
    public $activeUsersChange = 0;
    public $registeredUsersChange = 0;
    public $expiredCertificatesChange = 0;
    public $suspendedSubscriptionsChange = 0;

    public $received = 0;
    public $toPay = 0;
    public $paid = 0;

    public $courses = [];
    public $fields = [];
    public $recentUsers = [];
    public $recentTransactions = [];
    public $coursesParticipation = [];
    public $notes = '';
    public $savedNotes = [];
    public array $membersDatas = [];
    public array $recordDatas = [];
    public array $labels = [];
    public array $monthlyLabels = [];
    public array $monthlyIncomeData = [];
    public array $monthlyExpenseData = [];

    public function render()
    {
        Log::info('Dashboard render method called');
        return view('livewire.dashboard');
    }

    public function mount()
    {
        Log::info('Dashboard mount started');
        $startTime = microtime(true);

        $this->dayName = Carbon::now()->locale('it_IT')->dayName;
        Log::info('Day name set', ['day' => $this->dayName]);

        $this->loadBasicStats();
        $this->loadUserStats();
        $this->loadFinancialStats();
        $this->loadRecentData();
        $this->loadSavedNotes();

        $endTime = microtime(true);
        $executionTime = round(($endTime - $startTime) * 1000, 2);
        Log::info('Dashboard mount completed', [
            'execution_time_ms' => $executionTime,
            'active_users' => $this->activeUsers,
            'courses_count' => count($this->courses),
            'participation_count' => count($this->coursesParticipation)
        ]);
    }

    private function loadBasicStats()
    {
        Log::info('Loading basic stats');
        $startTime = microtime(true);

        try {
            $this->totMembers = \App\Models\Member::count();
            $this->totSuppliers = \App\Models\Supplier::count();
            Log::info('Basic counts loaded', [
                'total_members' => $this->totMembers,
                'total_suppliers' => $this->totSuppliers
            ]);

            // Calculate today's income and expenses
            $this->totTodayIn = 0;
            $todayRecordsIn = \App\Models\Record::where('type', 'IN')
                ->where('date', date("Y-m-d"))
                ->get();

            foreach ($todayRecordsIn as $record) {
                foreach ($record->rows as $row) {
                    $this->totTodayIn += $row->amount;
                }
            }

            $this->totTodayOut = 0;
            $todayRecordsOut = \App\Models\Record::where('type', 'OUT')
                ->where('date', date("Y-m-d"))
                ->get();

            foreach ($todayRecordsOut as $record) {
                foreach ($record->rows as $row) {
                    $this->totTodayOut += $row->amount;
                }
            }

            $endTime = microtime(true);
            Log::info('Basic stats loaded successfully', [
                'today_income' => $this->totTodayIn,
                'today_expenses' => $this->totTodayOut,
                'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
            ]);
        } catch (\Exception $e) {
            Log::error('Error loading basic stats', [
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine()
            ]);
        }
    }

    private function loadUserStats()
    {
        Log::info('Loading user stats');
        $startTime = microtime(true);

        try {
            $this->activeUsers = \App\Models\Member::where('is_archived', 0)->orWhere('is_archived', NULL)->count();
            $this->registeredUsers = \App\Models\Member::where('current_status', 2)->count();
            $this->suspendedSubscriptions = \App\Models\Member::where('current_status', 1)->count();

            Log::info('User counts loaded', [
                'active_users' => $this->activeUsers,
                'registered_users' => $this->registeredUsers,
                'suspended_subscriptions' => $this->suspendedSubscriptions
            ]);

            $this->expiredCertificates = \App\Models\Member::whereHas('certificates', function ($query) {
                $query->where('expire_date', '<', now());
            })->whereDoesntHave('certificates', function ($query) {
                $query->where('expire_date', '>=', now());
            })->count();

            Log::info('Expired certificates count', ['expired_certificates' => $this->expiredCertificates]);

            // Calculate changes from last month
            $lastMonth = now()->subMonth();
            $endOfLastMonth = $lastMonth->copy()->endOfMonth();

            $lastMonthActiveUsers = \App\Models\Member::where('is_archived', false)
                ->where('created_at', '<=', $endOfLastMonth)
                ->count();
            $lastMonthRegisteredUsers = \App\Models\Member::where('current_status', 2)
                ->where('updated_at', '<=', $endOfLastMonth)
                ->count();
            $lastMonthSuspendedSubscriptions = \App\Models\Member::where('current_status', 1)
                ->where('updated_at', '<=', $endOfLastMonth)
                ->count();
            $lastMonthExpiredCertificates = \App\Models\Member::whereHas('certificates', function ($query) use ($endOfLastMonth) {
                $query->where('expire_date', '<', $endOfLastMonth);
            })->whereDoesntHave('certificates', function ($query) use ($endOfLastMonth) {
                $query->where('expire_date', '>=', $endOfLastMonth);
            })->count();

            $this->activeUsersChange = $this->activeUsers - $lastMonthActiveUsers;
            $this->registeredUsersChange = $this->registeredUsers - $lastMonthRegisteredUsers;
            $this->expiredCertificatesChange = $this->expiredCertificates - $lastMonthExpiredCertificates;
            $this->suspendedSubscriptionsChange = $this->suspendedSubscriptions - $lastMonthSuspendedSubscriptions;

            $endTime = microtime(true);
            Log::info('User stats loaded successfully', [
                'changes' => [
                    'active_users' => $this->activeUsersChange,
                    'registered_users' => $this->registeredUsersChange,
                    'expired_certificates' => $this->expiredCertificatesChange,
                    'suspended_subscriptions' => $this->suspendedSubscriptionsChange
                ],
                'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
            ]);
        } catch (\Exception $e) {
            Log::error('Error loading user stats', [
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine()
            ]);
        }
    }

    private function loadFinancialStats()
    {
        Log::info('Loading financial stats');
        $startTime = microtime(true);

        try {
            $currentMonth = now()->format('Y-m');
            $currentDate = now()->format('Y-m-d');
            Log::info('Calculating financial stats for month', ['month' => $currentMonth]);

            $this->received = \App\Models\Record::where('type', 'IN')
                ->whereRaw('DATE_FORMAT(date, "%Y-%m") = ?', [$currentMonth])
                ->where(function ($query) {
                    $query->where('deleted', false)->orWhere('deleted', null);
                })
                ->sum('amount') ?? 0;

            $this->paid = \App\Models\Record::where('type', 'OUT')
                ->whereRaw('DATE_FORMAT(date, "%Y-%m") = ?', [$currentMonth])
                ->where('data_pagamento', '<=', $currentDate)
                ->where(function ($query) {
                    $query->where('deleted', false)->orWhere('deleted', null);
                })
                ->sum('amount') ?? 0;

            $this->toPay = \App\Models\Record::where('type', 'OUT')
                ->whereRaw('DATE_FORMAT(date, "%Y-%m") = ?', [$currentMonth])
                ->where(function ($query) use($currentDate) {
                    $query->where('data_pagamento', '>', $currentDate)
                        ->orWhereNull('data_pagamento');
                })
                ->where(function ($query) {
                    $query->where('deleted', false)->orWhere('deleted', null);
                })
                ->sum('amount') ?? 0;

            $endTime = microtime(true);
            Log::info('Financial stats loaded successfully', [
                'received' => $this->received,
                'paid' => $this->paid,
                'to_pay' => $this->toPay,
                'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
            ]);
        } catch (\Exception $e) {
            Log::error('Error loading financial stats', [
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine()
            ]);
        }
    }

    private function loadRecentData()
    {
        Log::info('Loading recent data');
        $startTime = microtime(true);

        try {
            // Load recent users
            $recentMembers = \App\Models\Member::where('is_archived', 0)
                ->orWhere('is_archived', NULL)
                ->orderBy('created_at', 'desc')
                ->limit(5)
                ->get();

            $this->recentUsers = $recentMembers->map(function ($member) {
                return [
                    'surname' => strtoupper($member->last_name),
                    'name' => strtoupper($member->first_name),
                    'phone' => $member->phone ?? '',
                    'email' => $member->email ?? ''
                ];
            })->toArray();

            Log::info('Recent users loaded', ['count' => count($this->recentUsers)]);

            // Load recent transactions
            $recentRecords = \App\Models\Record::where('date', '>=', now()->subDays(30))
                ->with(['member', 'supplier'])
                ->orderBy('date', 'desc')
                ->orderBy('created_at', 'desc')
                ->limit(10)
                ->get();

            $this->recentTransactions = $recentRecords->map(function ($record) {
                if ($record->type == 'IN') {
                    $name = $record->member ?
                        strtoupper($record->member->last_name) . ' ' . strtoupper($record->member->first_name) :
                        'MEMBRO SCONOSCIUTO';
                } else {
                    $name = $record->supplier ?
                        strtoupper($record->supplier->name) :
                        'FORNITORE SCONOSCIUTO';
                }

                $totalAmount = 0;
                foreach ($record->rows as $row) {
                    $totalAmount += $row->amount;
                }

                return [
                    'name' => $name,
                    'amount' => $totalAmount,
                    'type' => $record->type == 'IN' ? 'ENTRATA' : 'USCITA'
                ];
            })->toArray();

            Log::info('Recent transactions loaded', ['count' => count($this->recentTransactions)]);

            $this->loadCoursesData();
            $this->loadCoursesParticipation();

            $endTime = microtime(true);
            Log::info('Recent data loaded successfully', [
                'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
            ]);
        } catch (\Exception $e) {
            Log::error('Error loading recent data', [
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine()
            ]);
        }
    }

    private function loadCoursesData()
    {
        Log::info('Loading courses data');
        $startTime = microtime(true);

        try {
            $today = now()->format('N');
            $dayNames = [
                1 => 'lun',
                2 => 'mar',
                3 => 'mer',
                4 => 'gio',
                5 => 'ven',
                6 => 'sab',
                7 => 'dom'
            ];
            $todayName = $dayNames[$today];

            Log::info('Searching courses for today', [
                'today_number' => $today,
                'today_name' => $todayName
            ]);

            $memberCourses = \App\Models\MemberCourse::with(['course.level', 'course.frequency', 'member'])
                ->whereIn('status', [0, 1])
                ->whereHas('course', function ($query) {
                    $query->whereNotNull('when');
                })
                ->get();

            Log::info('Total member courses found', [
                'count' => $memberCourses->count()
            ]);

            $activeCourses = $memberCourses->filter(function ($memberCourse) use ($todayName) {
                try {
                    $whenData = json_decode($memberCourse->course->when, true);

                    if (!is_array($whenData)) {
                        return false;
                    }

                    foreach ($whenData as $schedule) {
                        if (
                            isset($schedule['day']) &&
                            is_array($schedule['day']) &&
                            in_array($todayName, $schedule['day'])
                        ) {
                            return true;
                        }
                    }
                } catch (\Exception $e) {
                    Log::debug('Error parsing course schedule', [
                        'member_course_id' => $memberCourse->id,
                        'course_id' => $memberCourse->course->id,
                        'when' => $memberCourse->course->when,
                        'error' => $e->getMessage()
                    ]);
                }
                return false;
            });

            Log::info('Active courses found for today', [
                'count' => $activeCourses->count(),
                'course_ids' => $activeCourses->pluck('course.id')->toArray()
            ]);

            $this->courses = $activeCourses->map(function ($memberCourse) use ($todayName) {
                $whenData = json_decode($memberCourse->course->when, true);

                Log::debug('Processing course schedule', [
                    'member_course_id' => $memberCourse->id,
                    'course_id' => $memberCourse->course->id,
                    'course_name' => $memberCourse->course->name,
                    'when_data' => $whenData,
                    'looking_for_day' => $todayName
                ]);

                $todaySchedule = null;

                if (is_array($whenData)) {
                    foreach ($whenData as $schedule) {
                        if (
                            isset($schedule['day']) &&
                            is_array($schedule['day']) &&
                            in_array($todayName, $schedule['day'])
                        ) {
                            $todaySchedule = $schedule;
                            Log::debug('Found matching schedule', [
                                'schedule' => $schedule,
                                'course_id' => $memberCourse->course->id
                            ]);
                            break;
                        }
                    }
                }

                if (!$todaySchedule) {
                    Log::debug('No matching schedule found for today', [
                        'course_id' => $memberCourse->course->id,
                        'when_data' => $whenData
                    ]);
                    return null;
                }

                $days = implode('-', array_map('ucfirst', $todaySchedule['day']));
                $course = $memberCourse->course;

                $courseName = $course->name ?? 'Corso Sconosciuto';
                $levelName = $course->level?->name ?? '';
                $frequencyName = $course->frequency?->name ?? '';
                $typeName = $course->getFormattedTypeField() ?? '';

                $courseNameParts = [$courseName];
                if ($levelName) $courseNameParts[] = $levelName;
                if ($typeName) $courseNameParts[] = $typeName;
                if ($frequencyName) $courseNameParts[] = $frequencyName;

                $fullCourseName = implode(' - ', $courseNameParts);

                return [
                    'time' => $todaySchedule['from'] . ' - ' . $todaySchedule['to'],
                    'course_name' => $courseName,
                    'full_name' => $fullCourseName,
                    'level_name' => $levelName,
                    'type_name' => $typeName,
                    'frequency_name' => $frequencyName,
                    'days' => $days,
                    'type' => $course->type ?? 'Standard',
                    'from_time' => $todaySchedule['from'],
                    'course_id' => $course->id,
                    'member_course_id' => $memberCourse->id
                ];
            })->filter()->values();

            $sortedCourses = $this->courses->sortBy('from_time')->take(5);

            Log::info('Courses sorted by time', [
                'sorted_courses' => $sortedCourses->map(function ($course) {
                    return [
                        'time' => $course['time'],
                        'from_time' => $course['from_time'],
                        'course_name' => $course['course_name'],
                        'course_id' => $course['course_id']
                    ];
                })->toArray()
            ]);

            $this->courses = $sortedCourses->map(function ($course) {
                unset($course['from_time'], $course['member_course_id'], $course['course_id']);
                return $course;
            })->toArray();

            $endTime = microtime(true);
            Log::info('Courses data loaded successfully', [
                'final_courses_count' => count($this->courses),
                'execution_time_ms' => round(($endTime - $startTime) * 1000, 2),
                'final_courses_display' => $this->courses
            ]);
        } catch (\Exception $e) {
            Log::error('Error loading courses data', [
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine()
            ]);
            $this->courses = [];
        }
    }

    private function loadCoursesParticipation()
    {
        Log::info('Loading courses participation');
        $startTime = microtime(true);

        try {
            // Conta le partecipazioni per corso (include tutti gli status)
            $courseStats = \App\Models\MemberCourse::with(['course.level', 'course.frequency'])
                ->whereIn('status', [0, 1]) // Include both statuses
                ->selectRaw('course_id, COUNT(*) as participants')
                ->groupBy('course_id')
                ->orderBy('participants', 'desc')
                ->limit(4)
                ->get();

            Log::info('Course participation stats', [
                'courses_found' => $courseStats->count(),
                'stats' => $courseStats->map(function ($stat) {
                    $course = $stat->course;
                    $levelName = is_object($course->level) ? $course->level->name : '';
                    $frequencyName = is_object($course->frequency) ? $course->frequency->name : '';

                    return [
                        'course_id' => $stat->course_id,
                        'course_name' => $course->name ?? 'Unknown',
                        'level_name' => $levelName,
                        'frequency_name' => $frequencyName,
                        'participants' => $stat->participants
                    ];
                })->toArray()
            ]);

            $totalParticipants = $courseStats->sum('participants');

            $this->coursesParticipation = $courseStats->map(function ($stat) use ($totalParticipants) {
                $percentage = $totalParticipants > 0 ? ($stat->participants / $totalParticipants) * 100 : 0;
                $course = $stat->course;
                $courseName = $course->name ?? 'Corso Sconosciuto';
                $levelName = is_object($course->level) ? $course->level->name : '';
                $frequencyName = is_object($course->frequency) ? $course->frequency->name : '';
                $typeName = $course->getFormattedTypeField() ?? '';

                // Build display name with level and frequency
                $displayNameParts = [$courseName];
                if ($levelName) $displayNameParts[] = $levelName;
                if ($typeName) $displayNameParts[] = $typeName;
                if ($frequencyName) $displayNameParts[] = $frequencyName;

                $displayName = implode(' - ', $displayNameParts);

                // Assegna colori basati sul nome del corso
                $color = $this->getCourseColor($courseName);

                return [
                    'course_name' => $displayName,
                    'base_course_name' => $courseName,
                    'level_name' => $levelName,
                    'type_name' => $typeName,
                    'frequency_name' => $frequencyName,
                    'participants' => $stat->participants,
                    'percentage' => round($percentage, 1),
                    'color' => $color
                ];
            })->toArray();

            $endTime = microtime(true);
            Log::info('Courses participation loaded successfully', [
                'total_participants' => $totalParticipants,
                'participation_data' => $this->coursesParticipation,
                'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
            ]);
        } catch (\Exception $e) {
            Log::error('Error loading courses participation', [
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine()
            ]);
            $this->coursesParticipation = [];
        }
    }

    private function getCourseColor($courseName)
    {
        $colors = [
            'padel',
            'tennis',
            'pallavolo',
            'yoga',
            'blue',
            'pink',
            'green',
            'red',
            'indigo',
            'amber',
            'cyan',
            'lime'
        ];
        $hash = crc32($courseName);
        $colorIndex = abs($hash) % count($colors);
        $assignedColor = $colors[$colorIndex];

        Log::debug('Course color assigned', [
            'course_name' => $courseName,
            'hash' => $hash,
            'color_index' => $colorIndex,
            'assigned_color' => $assignedColor
        ]);

        return $assignedColor;
    }

    private function loadSavedNotes()
    {
        Log::info('Loading saved notes');

        try {
            $this->savedNotes = session()->get('dashboard_notes', []);

            Log::info('Saved notes loaded', [
                'notes_count' => count($this->savedNotes)
            ]);
        } catch (\Exception $e) {
            Log::error('Error loading saved notes', [
                'error' => $e->getMessage()
            ]);
            $this->savedNotes = [];
        }
    }

    private function saveSavedNotes()
    {
        try {
            session()->put('dashboard_notes', $this->savedNotes);

            Log::info('Notes saved to session', [
                'notes_count' => count($this->savedNotes)
            ]);
        } catch (\Exception $e) {
            Log::error('Error saving notes', [
                'error' => $e->getMessage()
            ]);
        }
    }

    public function saveNote()
    {
        Log::info('Save note called', ['note_text' => $this->notes]);

        try {
            if (trim($this->notes) !== '') {
                $newNote = [
                    'id' => uniqid(),
                    'text' => trim($this->notes),
                    'created_at' => now()->timezone('Europe/Rome')->format('d/m/Y H:i'),
                    'completed' => false
                ];

                array_unshift($this->savedNotes, $newNote);

                $this->saveSavedNotes();

                $this->notes = '';

                $this->dispatchBrowserEvent('note-saved');

                Log::info('Note saved successfully', [
                    'note_id' => $newNote['id'],
                    'total_notes' => count($this->savedNotes)
                ]);
            } else {
                Log::warning('Attempted to save empty note');
            }
        } catch (\Exception $e) {
            Log::error('Error saving note', [
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine()
            ]);
        }
    }

    public function completeNote($noteId)
    {
        Log::info('Complete note called', ['note_id' => $noteId]);

        try {
            $initialCount = count($this->savedNotes);

            $this->savedNotes = array_filter($this->savedNotes, function ($note) use ($noteId) {
                return $note['id'] !== $noteId;
            });

            $this->savedNotes = array_values($this->savedNotes);

            $finalCount = count($this->savedNotes);

            if ($initialCount > $finalCount) {
                $this->saveSavedNotes();

                $this->dispatchBrowserEvent('note-completed');

                Log::info('Note completed successfully', [
                    'note_id' => $noteId,
                    'remaining_notes' => $finalCount
                ]);
            } else {
                Log::warning('Note not found for completion', ['note_id' => $noteId]);
            }
        } catch (\Exception $e) {
            Log::error('Error completing note', [
                'note_id' => $noteId,
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine()
            ]);
        }
    }

    public function addMember()
    {
        Log::info('Redirecting to add member');
        return redirect()->to('/members?new=1');
    }

    public function addSupplier()
    {
        Log::info('Redirecting to add supplier');
        return redirect()->to('/suppliers?new=1');
    }

    public function addIn()
    {
        Log::info('Redirecting to add income record');
        return redirect()->to('/in?new=1');
    }

    public function addOut()
    {
        Log::info('Redirecting to add expense record');
        return redirect()->to('/out?new=1');
    }

    public function debugCourses()
    {
        Log::info('=== DEBUG COURSES CALLED ===');

        $today = now()->format('N');
        $dayNames = [
            1 => 'lun',
            2 => 'mar',
            3 => 'mer',
            4 => 'gio',
            5 => 'ven',
            6 => 'sab',
            7 => 'dom'
        ];
        $todayName = $dayNames[$today];

        // Get all member courses
        $allCourses = \App\Models\MemberCourse::with('course')->get();

        Log::info('All courses debug', [
            'total_courses' => $allCourses->count(),
            'today_name' => $todayName,
            'courses' => $allCourses->map(function ($mc) {
                return [
                    'id' => $mc->id,
                    'status' => $mc->status,
                    'when' => $mc->when,
                    'course_name' => $mc->course->name ?? 'Unknown'
                ];
            })->toArray()
        ]);

        $this->dispatchBrowserEvent('debug-completed');
    }

    public function activateTestCourses()
    {
        try {
            $updated = \App\Models\MemberCourse::whereIn('id', [21, 22, 23, 24])
                ->update(['status' => 1]);

            Log::info('Activated test courses', ['updated_count' => $updated]);

            $this->loadCoursesData();
            $this->loadCoursesParticipation();

            $this->dispatchBrowserEvent('courses-activated', [
                'message' => "Attivati $updated corsi per test"
            ]);
        } catch (\Exception $e) {
            Log::error('Error activating courses', ['error' => $e->getMessage()]);
        }
    }

    private function getLabels()
    {
        $labels = array();
        for ($i = 6; $i >= 0; $i--) {
            $labels[] = date("d/M", strtotime('-' . $i . ' days'));
        }
        return $labels;
    }

    private function getRecordData($type)
    {
        $data = [];
        for ($i = 6; $i >= 0; $i--) {
            $found = false;
            $records = $type == 'IN' ? $this->in : $this->out;

            foreach ($records as $record) {
                if (date("Y-m-d", strtotime($record->date)) == date("Y-m-d", strtotime('-' . $i . ' days'))) {
                    $data[] = $record->total;
                    $found = true;
                    break;
                }
            }
            if (!$found) {
                $data[] = 0;
            }
        }
        return $data;
    }

    private function getMemberData()
    {
        $data = [];
        for ($i = 6; $i >= 0; $i--) {
            $found = false;
            foreach ($this->members as $member) {
                if (date("Y-m-d", strtotime($member->created_at)) == date("Y-m-d", strtotime('-' . $i . ' days'))) {
                    $data[] = $member->total;
                    $found = true;
                    break;
                }
            }
            if (!$found) {
                $data[] = 0;
            }
        }
        return $data;
    }
}
