<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\ApiBaseController;
use App\Http\Requests\Api\WeekoffRule\DeleteRequest;
use App\Http\Requests\Api\WeekoffRule\IndexRequest;
use App\Http\Requests\Api\WeekoffRule\StoreRequest;
use App\Http\Requests\Api\WeekoffRule\UpdateRequest;
use App\Models\WeekoffRule;
use Carbon\Carbon;
use Examyou\RestAPI\ApiResponse;
use Illuminate\Database\Eloquent\Builder;

class WeekoffRuleController extends ApiBaseController
{
    protected $model = WeekoffRule::class;

    protected $indexRequest = IndexRequest::class;
    protected $storeRequest = StoreRequest::class;
    protected $updateRequest = UpdateRequest::class;
    protected $deleteRequest = DeleteRequest::class;

    protected function modifyIndex($query)
    {
        $request = request();
        if ($request->has('is_active')) {
            $query->where('is_active', filter_var($request->is_active, FILTER_VALIDATE_BOOLEAN));
        }

        if ($request->has('is_company_default')) {
            $query->where('is_company_default', filter_var($request->is_company_default, FILTER_VALIDATE_BOOLEAN));
        }
  

        return $query->orderByDesc('effective_from');
    }

    public function storing(WeekoffRule $weekoffRule)
    {
        $request = request();
        $company = company();
        $user = user();

        $weekoffRule->company_id = $company?->id;
        $weekoffRule->created_by = $user?->id;
        $weekoffRule->updated_by = $user?->id;
        $weekoffRule->effective_from = Carbon::parse($request->effective_from)->format('Y-m-d');
        $weekoffRule->pattern = $this->normalizePattern($request->pattern ?? []);

        if ($weekoffRule->is_company_default) {
            $this->clearCompanyDefaults($weekoffRule->company_id);
        }

        return $weekoffRule;
    }

    public function updating(WeekoffRule $weekoffRule)
    {
        $request = request();
        $weekoffRule->updated_by = user()?->id;

        if ($request->has('effective_from')) {
            $weekoffRule->effective_from = Carbon::parse($request->effective_from)->format('Y-m-d');
        }

        if ($request->has('pattern')) {
            $weekoffRule->pattern = $this->normalizePattern($request->pattern);
        }

        if ($request->has('is_company_default') && filter_var($request->is_company_default, FILTER_VALIDATE_BOOLEAN)) {
            $this->clearCompanyDefaults($weekoffRule->company_id, $weekoffRule->id);
            $weekoffRule->is_company_default = true;
        }

        return $weekoffRule;
    }

    public function setCompanyDefault($xid)
    {
        $id = $this->getIdFromHash($xid);
        $weekoffRule = WeekoffRule::findOrFail($id);

        $this->clearCompanyDefaults($weekoffRule->company_id, $weekoffRule->id);

        $weekoffRule->is_company_default = true;
        $weekoffRule->save();

        return ApiResponse::make('Company default updated', ['xid' => $weekoffRule->xid]);
    }

    protected function clearCompanyDefaults(?int $companyId, ?int $exceptId = null): void
    {
        if (!$companyId) {
            return;
        }

        WeekoffRule::where('company_id', $companyId)
            ->when($exceptId, fn(Builder $query) => $query->where('id', '!=', $exceptId))
            ->update(['is_company_default' => false]);
    }

    protected function normalizePattern(array $pattern): array
    {
        $normalized = [
            'weeks' => [],
        ];

        $weeks = $pattern['weeks'] ?? $pattern;

        foreach ($weeks as $key => $days) {
            $weekKey = $this->formatWeekKey($key);
            $normalized['weeks'][$weekKey] = collect($days ?? [])
                ->map(fn($day) => (int)$day)
                ->filter(fn($day) => $day >= 0 && $day <= 6)
                ->unique()
                ->values()
                ->all();
        }

        if (isset($pattern['days']) && is_array($pattern['days'])) {
            $normalized['days'] = collect($pattern['days'])
                ->map(fn($day) => (int)$day)
                ->filter(fn($day) => $day >= 0 && $day <= 6)
                ->unique()
                ->values()
                ->all();
        }

        if (isset($pattern['half_days']) && is_array($pattern['half_days'])) {
            $normalized['half_days'] = $this->normalizeHalfDays($pattern['half_days']);
        }

        return $normalized;
    }

    protected function normalizeHalfDays(array $halfDays): array
    {
        $normalized = [];

        foreach ($halfDays as $key => $days) {
            if ($key === 'days') {
                $normalized['days'] = collect($days)
                    ->map(fn($day) => (int)$day)
                    ->filter(fn($day) => $day >= 0 && $day <= 6)
                    ->unique()
                    ->values()
                    ->all();

                continue;
            }

            $weekKey = $this->formatWeekKey($key);

            $normalized[$weekKey] = collect($days ?? [])
                ->map(fn($day) => (int)$day)
                ->filter(fn($day) => $day >= 0 && $day <= 6)
                ->unique()
                ->values()
                ->all();
        }

        return $normalized;
    }

    protected function formatWeekKey($key): string
    {
        if (is_string($key) && str_starts_with($key, 'week_')) {
            return $key;
        }

        return 'week_' . (int)$key;
    }
}

