<?php

namespace App\Services\Employee;

use App\Services\BaseService;
use App\Repositories\DailyReportRepository;
use App\Models\EmployeeDailyReport;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class DailyReportService extends BaseService
{
    protected DailyReportRepository $dailyReportRepository;

    public function __construct(DailyReportRepository $repository)
    {
        parent::__construct($repository);
        $this->dailyReportRepository = $repository;
    }

    /**
     * Get reports with employee details
     */
    public function getAllWithEmployee(): Collection
    {
        return $this->dailyReportRepository->getWithEmployee();
    }

    /**
     * Get reports by employee
     */
    public function getByEmployee(string $employeeId): Collection
    {
        return $this->dailyReportRepository->getByEmployee($employeeId);
    }

    /**
     * Get reports by date
     */
    public function getByDate(string $date): Collection
    {
        return $this->dailyReportRepository->getByDate($date);
    }

    /**
     * Get reports for date range
     */
    public function getByDateRange(string $start, string $end): Collection
    {
        return $this->dailyReportRepository->getByDateRange($start, $end);
    }

    /**
     * Get monthly reports for an employee
     */
    public function getMonthly(string $employeeId, int $month, int $year): Collection
    {
        return $this->dailyReportRepository->getMonthly($employeeId, $month, $year);
    }

    /**
     * Get reports with overtime
     */
    public function getWithOvertime(int $month, int $year): Collection
    {
        return $this->dailyReportRepository->getWithOvertime($month, $year);
    }

    /**
     * Get manual entries
     */
    public function getManualEntries(string $start, string $end): Collection
    {
        return $this->dailyReportRepository->getManualEntries($start, $end);
    }

    /**
     * Create or update daily report
     */
    public function createOrUpdate(array $data): EmployeeDailyReport
    {
        return DB::transaction(function () use ($data) {
            $existing = $this->dailyReportRepository->findByEmployeeAndDate(
                $data['employee_id'],
                $data['date']
            );

            if ($existing) {
                $existing->update($data);
                return $existing->fresh();
            }

            return $this->create($data);
        });
    }

    /**
     * Bulk create/update reports
     */
    public function bulkCreateOrUpdate(string $date, array $reportsData): int
    {
        return DB::transaction(function () use ($date, $reportsData) {
            $count = 0;
            foreach ($reportsData as $data) {
                $data['date'] = $date;
                $this->createOrUpdate($data);
                $count++;
            }
            return $count;
        });
    }

    /**
     * Get monthly summary for an employee
     */
    public function getMonthlySummary(string $employeeId, int $month, int $year): array
    {
        $reports = $this->getMonthly($employeeId, $month, $year);

        return [
            'total_days' => $reports->count(),
            'present_full' => $reports->filter(fn($r) =>
                $r->first_half === EmployeeDailyReport::HALF_PRESENT &&
                $r->second_half === EmployeeDailyReport::HALF_PRESENT
            )->count(),
            'half_days' => $reports->filter(fn($r) =>
                ($r->first_half === EmployeeDailyReport::HALF_PRESENT xor
                 $r->second_half === EmployeeDailyReport::HALF_PRESENT)
            )->count(),
            'absent' => $reports->filter(fn($r) =>
                $r->first_half === EmployeeDailyReport::HALF_ABSENT &&
                $r->second_half === EmployeeDailyReport::HALF_ABSENT
            )->count(),
            'total_work_hours' => $reports->sum('work_hours'),
            'total_overtime' => $reports->sum('over_time'),
            'total_auth_ot' => $reports->sum('auth_ot'),
            'total_auth_coff' => $reports->sum('auth_coff'),
            'late_arrivals' => $reports->filter(fn($r) => !empty($r->late_in))->count(),
            'early_departures' => $reports->filter(fn($r) => !empty($r->early_out))->count(),
            'manual_entries' => $reports->filter(fn($r) => $r->man_entry)->count(),
        ];
    }

    /**
     * Get calendar view data
     */
    public function getCalendarData(string $employeeId, int $month, int $year): array
    {
        $reports = $this->getMonthly($employeeId, $month, $year);

        $calendar = [];
        foreach ($reports as $report) {
            $day = $report->date->day;
            $calendar[$day] = [
                'date' => $report->date->toDateString(),
                'shift' => $report->shift,
                'first_half' => $report->first_half,
                'second_half' => $report->second_half,
                'work_hours' => $report->work_hours,
                'overtime' => $report->over_time,
                'is_manual' => $report->man_entry,
                'status' => $report->summary,
            ];
        }

        return $calendar;
    }

    /**
     * Mark as manual entry
     */
    public function markManualEntry(int $id, string $reason): EmployeeDailyReport
    {
        return DB::transaction(function () use ($id, $reason) {
            $report = $this->findByIdOrFail($id);
            $report->update([
                'man_entry' => true,
                'reason' => $reason,
            ]);

            $this->logAction('Manual entry marked', [
                'report_id' => $id,
                'employee_id' => $report->employee_id,
                'reason' => $reason,
            ]);

            return $report->fresh();
        });
    }
}
