<?php

namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Controller;
use App\Models\Finance\FundSchedule;
use App\Services\FundScheduleService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class FundScheduleController extends Controller
{
    public function __construct(
        private FundScheduleService $fundScheduleService
    ) {}

    /**
     * 일정 목록 조회
     */
    public function index(Request $request): JsonResponse|Response
    {
        $schedules = $this->fundScheduleService->getSchedules(
            $request->all(),
            $request->integer('per_page', 15)
        );

        // HTMX 요청인 경우 HTML 반환
        if ($request->header('HX-Request')) {
            return response(view('finance.fund-schedules.partials.table', compact('schedules')));
        }

        return response()->json([
            'success' => true,
            'data' => $schedules->items(),
            'meta' => [
                'current_page' => $schedules->currentPage(),
                'last_page' => $schedules->lastPage(),
                'per_page' => $schedules->perPage(),
                'total' => $schedules->total(),
            ],
        ]);
    }

    /**
     * 캘린더용 월별 일정 조회
     */
    public function calendar(Request $request): JsonResponse|Response
    {
        $year = $request->integer('year', now()->year);
        $month = $request->integer('month', now()->month);

        $calendarData = $this->fundScheduleService->getCalendarData($year, $month);
        $summary = $this->fundScheduleService->getMonthlySummary($year, $month);

        // HTMX 요청인 경우 캘린더 HTML 반환
        if ($request->header('HX-Request')) {
            return response(view('finance.fund-schedules.partials.calendar', compact('year', 'month', 'calendarData', 'summary')));
        }

        return response()->json([
            'success' => true,
            'data' => [
                'year' => $year,
                'month' => $month,
                'schedules' => $calendarData,
                'summary' => $summary,
            ],
        ]);
    }

    /**
     * 일정 상세 조회
     */
    public function show(int $id): JsonResponse
    {
        $schedule = $this->fundScheduleService->getScheduleById($id);

        if (! $schedule) {
            return response()->json([
                'success' => false,
                'message' => '일정을 찾을 수 없습니다.',
            ], 404);
        }

        return response()->json([
            'success' => true,
            'data' => $schedule,
        ]);
    }

    /**
     * 일정 생성
     */
    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'title' => 'required|string|max:200',
            'description' => 'nullable|string',
            'schedule_type' => 'required|in:income,expense',
            'scheduled_date' => 'required|date',
            'amount' => 'required|numeric|min:0',
            'currency' => 'nullable|string|max:3',
            'related_bank_account_id' => 'nullable|integer|exists:bank_accounts,id',
            'counterparty' => 'nullable|string|max:200',
            'category' => 'nullable|string|max:50',
            'status' => 'nullable|in:pending,completed,cancelled',
            'is_recurring' => 'nullable|boolean',
            'recurrence_rule' => 'nullable|in:daily,weekly,monthly,yearly',
            'recurrence_end_date' => 'nullable|date|after:scheduled_date',
            'memo' => 'nullable|string',
        ]);

        $schedule = $this->fundScheduleService->createSchedule($validated);

        return response()->json([
            'success' => true,
            'message' => '일정이 등록되었습니다.',
            'data' => $schedule,
        ], 201);
    }

    /**
     * 일정 수정
     */
    public function update(Request $request, int $id): JsonResponse
    {
        $schedule = $this->fundScheduleService->getScheduleById($id);

        if (! $schedule) {
            return response()->json([
                'success' => false,
                'message' => '일정을 찾을 수 없습니다.',
            ], 404);
        }

        $validated = $request->validate([
            'title' => 'sometimes|required|string|max:200',
            'description' => 'nullable|string',
            'schedule_type' => 'sometimes|required|in:income,expense',
            'scheduled_date' => 'sometimes|required|date',
            'amount' => 'sometimes|required|numeric|min:0',
            'currency' => 'nullable|string|max:3',
            'related_bank_account_id' => 'nullable|integer|exists:bank_accounts,id',
            'counterparty' => 'nullable|string|max:200',
            'category' => 'nullable|string|max:50',
            'status' => 'nullable|in:pending,completed,cancelled',
            'is_recurring' => 'nullable|boolean',
            'recurrence_rule' => 'nullable|in:daily,weekly,monthly,yearly',
            'recurrence_end_date' => 'nullable|date',
            'memo' => 'nullable|string',
        ]);

        $schedule = $this->fundScheduleService->updateSchedule($schedule, $validated);

        return response()->json([
            'success' => true,
            'message' => '일정이 수정되었습니다.',
            'data' => $schedule,
        ]);
    }

    /**
     * 일정 삭제 (Soft Delete)
     */
    public function destroy(Request $request, int $id): JsonResponse|Response
    {
        $schedule = $this->fundScheduleService->getScheduleById($id);

        if (! $schedule) {
            return response()->json([
                'success' => false,
                'message' => '일정을 찾을 수 없습니다.',
            ], 404);
        }

        $this->fundScheduleService->deleteSchedule($schedule);

        // HTMX 요청인 경우 갱신된 캘린더 반환
        if ($request->header('HX-Request')) {
            $year = $request->integer('year', now()->year);
            $month = $request->integer('month', now()->month);
            $calendarData = $this->fundScheduleService->getCalendarData($year, $month);
            $summary = $this->fundScheduleService->getMonthlySummary($year, $month);

            return response(view('finance.fund-schedules.partials.calendar', compact('year', 'month', 'calendarData', 'summary')));
        }

        return response()->json([
            'success' => true,
            'message' => '일정이 삭제되었습니다.',
        ]);
    }

    /**
     * 상태 변경
     */
    public function updateStatus(Request $request, int $id): JsonResponse|Response
    {
        $schedule = $this->fundScheduleService->getScheduleById($id);

        if (! $schedule) {
            return response()->json([
                'success' => false,
                'message' => '일정을 찾을 수 없습니다.',
            ], 404);
        }

        $validated = $request->validate([
            'status' => 'required|in:pending,completed,cancelled',
            'completed_amount' => 'nullable|numeric|min:0',
            'completed_date' => 'nullable|date',
        ]);

        if ($validated['status'] === FundSchedule::STATUS_COMPLETED) {
            $schedule = $this->fundScheduleService->markAsCompleted(
                $schedule,
                $validated['completed_amount'] ?? null,
                $validated['completed_date'] ?? null
            );
        } elseif ($validated['status'] === FundSchedule::STATUS_CANCELLED) {
            $schedule = $this->fundScheduleService->markAsCancelled($schedule);
        } else {
            $schedule = $this->fundScheduleService->updateStatus($schedule, $validated['status']);
        }

        // HTMX 요청인 경우 갱신된 캘린더 반환
        if ($request->header('HX-Request')) {
            $year = $request->integer('year', now()->year);
            $month = $request->integer('month', now()->month);
            $calendarData = $this->fundScheduleService->getCalendarData($year, $month);
            $summary = $this->fundScheduleService->getMonthlySummary($year, $month);

            return response(view('finance.fund-schedules.partials.calendar', compact('year', 'month', 'calendarData', 'summary')));
        }

        return response()->json([
            'success' => true,
            'message' => '상태가 변경되었습니다.',
            'data' => $schedule,
        ]);
    }

    /**
     * 월별 일정 복사
     */
    public function copy(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'source_year' => 'required|integer|min:2000|max:2100',
            'source_month' => 'required|integer|min:1|max:12',
            'target_year' => 'required|integer|min:2000|max:2100',
            'target_month' => 'required|integer|min:1|max:12',
        ]);

        if ($validated['source_year'] === $validated['target_year']
            && $validated['source_month'] === $validated['target_month']) {
            return response()->json([
                'success' => false,
                'message' => '원본 월과 대상 월이 동일합니다.',
            ], 422);
        }

        $copiedCount = $this->fundScheduleService->copySchedulesToMonth(
            $validated['source_year'],
            $validated['source_month'],
            $validated['target_year'],
            $validated['target_month']
        );

        if ($copiedCount === 0) {
            return response()->json([
                'success' => false,
                'message' => '복사할 일정이 없습니다.',
            ], 422);
        }

        return response()->json([
            'success' => true,
            'message' => "{$copiedCount}건의 일정이 복사되었습니다.",
            'data' => ['copied_count' => $copiedCount],
        ]);
    }

    /**
     * 월별 요약 통계
     */
    public function summary(Request $request): JsonResponse
    {
        $year = $request->integer('year', now()->year);
        $month = $request->integer('month', now()->month);

        $summary = $this->fundScheduleService->getMonthlySummary($year, $month);

        return response()->json([
            'success' => true,
            'data' => $summary,
        ]);
    }

    /**
     * 예정 일정 조회
     */
    public function upcoming(Request $request): JsonResponse
    {
        $days = $request->integer('days', 30);
        $schedules = $this->fundScheduleService->getUpcomingSchedules($days);

        return response()->json([
            'success' => true,
            'data' => $schedules,
        ]);
    }
}
