<?php

namespace Modules\Configuration\Http\Controllers;

use App\Http\Controllers\Controller;
use Modules\Configuration\Models\GradingRule;
use Modules\Configuration\Models\DivisionRule;
use Modules\Configuration\Http\Requests\StoreGradingRuleRequest;
use Modules\Configuration\Http\Requests\UpdateGradingRuleRequest;
use Modules\Configuration\Http\Requests\StoreDivisionRuleRequest;
use Modules\Configuration\Http\Requests\UpdateDivisionRuleRequest;
use Modules\Academic\Models\AcademicYear;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
use Illuminate\Http\RedirectResponse;
use Modules\Configuration\Services\ConfigurationService;
use Illuminate\Support\Facades\DB;

class ConfigurationController extends Controller
{
    private ConfigurationService $configurationService;

    public function __construct(ConfigurationService $configurationService)
    {
        $this->configurationService = $configurationService;
        $this->middleware('auth');
    }

    /**
     * Display configuration dashboard
     */
    public function index(Request $request): Response
    {
        $this->authorize('viewAny', GradingRule::class);

        $filters = [
            'academic_year_id' => $request->academic_year_id,
            'search' => $request->search,
        ];

        $gradingRules = $this->configurationService->getGradingRules($filters);
        $divisionRules = $this->configurationService->getDivisionRules($filters);
        $academicYears = AcademicYear::orderBy('start_date', 'desc')->get();
        $statistics = $this->configurationService->getConfigurationStatistics();

        return Inertia::render('Configuration/Index', [
            'gradingRules' => $gradingRules,
            'divisionRules' => $divisionRules,
            'academicYears' => $academicYears,
            'statistics' => $statistics,
            'filters' => $filters,
        ]);
    }

    /**
     * Show grading rules management
     */
    public function gradingRules(Request $request): Response
    {
        $this->authorize('viewAny', GradingRule::class);

        $filters = [
            'academic_year_id' => $request->academic_year_id,
            'search' => $request->search,
        ];

        $gradingRules = $this->configurationService->getGradingRules($filters);
        $academicYears = AcademicYear::orderBy('start_date', 'desc')->get();

        return Inertia::render('Configuration/GradingRules', [
            'gradingRules' => $gradingRules,
            'academicYears' => $academicYears,
            'filters' => $filters,
            'defaultRules' => $this->configurationService->getDefaultGradingRules(),
        ]);
    }

    /**
     * Show division rules management
     */
    public function divisionRules(Request $request): Response
    {
        $this->authorize('viewAny', DivisionRule::class);

        $filters = [
            'academic_year_id' => $request->academic_year_id,
            'search' => $request->search,
        ];

        $divisionRules = $this->configurationService->getDivisionRules($filters);
        $academicYears = AcademicYear::orderBy('start_date', 'desc')->get();

        return Inertia::render('Configuration/DivisionRules', [
            'divisionRules' => $divisionRules,
            'academicYears' => $academicYears,
            'filters' => $filters,
            'defaultRules' => $this->configurationService->getDefaultDivisionRules(),
        ]);
    }

    /**
     * Store grading rule
     */
    public function storeGradingRule(StoreGradingRuleRequest $request): RedirectResponse
    {
        try {
            DB::beginTransaction();

            $this->configurationService->createGradingRule($request->validated());

            DB::commit();

            return back()->with('success', 'Grading rule created successfully.');

        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withInput()
                ->withErrors(['error' => 'Failed to create grading rule: ' . $e->getMessage()]);
        }
    }

    /**
     * Update grading rule
     */
    public function updateGradingRule(UpdateGradingRuleRequest $request, GradingRule $gradingRule): RedirectResponse
    {
        try {
            DB::beginTransaction();

            $this->configurationService->updateGradingRule($gradingRule, $request->validated());

            DB::commit();

            return back()->with('success', 'Grading rule updated successfully.');

        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withInput()
                ->withErrors(['error' => 'Failed to update grading rule: ' . $e->getMessage()]);
        }
    }

    /**
     * Delete grading rule
     */
    public function destroyGradingRule(GradingRule $gradingRule): RedirectResponse
    {
        $this->authorize('delete', $gradingRule);

        try {
            DB::beginTransaction();

            $gradingRule->delete();

            DB::commit();

            return back()->with('success', 'Grading rule deleted successfully.');

        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withErrors(['error' => 'Failed to delete grading rule: ' . $e->getMessage()]);
        }
    }

    /**
     * Store division rule
     */
    public function storeDivisionRule(StoreDivisionRuleRequest $request): RedirectResponse
    {
        try {
            DB::beginTransaction();

            $this->configurationService->createDivisionRule($request->validated());

            DB::commit();

            return back()->with('success', 'Division rule created successfully.');

        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withInput()
                ->withErrors(['error' => 'Failed to create division rule: ' . $e->getMessage()]);
        }
    }

    /**
     * Update division rule
     */
    public function updateDivisionRule(UpdateDivisionRuleRequest $request, DivisionRule $divisionRule): RedirectResponse
    {
        try {
            DB::beginTransaction();

            $this->configurationService->updateDivisionRule($divisionRule, $request->validated());

            DB::commit();

            return back()->with('success', 'Division rule updated successfully.');

        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withInput()
                ->withErrors(['error' => 'Failed to update division rule: ' . $e->getMessage()]);
        }
    }

    /**
     * Delete division rule
     */
    public function destroyDivisionRule(DivisionRule $divisionRule): RedirectResponse
    {
        $this->authorize('delete', $divisionRule);

        try {
            DB::beginTransaction();

            $divisionRule->delete();

            DB::commit();

            return back()->with('success', 'Division rule deleted successfully.');

        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withErrors(['error' => 'Failed to delete division rule: ' . $e->getMessage()]);
        }
    }

    /**
     * Copy rules from one academic year to another
     */
    public function copyRules(Request $request): RedirectResponse
    {
        $this->authorize('create', GradingRule::class);
        $this->authorize('create', DivisionRule::class);

        $validated = $request->validate([
            'source_academic_year_id' => 'required|exists:academic_years,id',
            'target_academic_year_id' => 'required|exists:academic_years,id|different:source_academic_year_id',
        ]);

        try {
            DB::beginTransaction();

            $results = $this->configurationService->copyRulesToAcademicYear(
                $validated['source_academic_year_id'],
                $validated['target_academic_year_id']
            );

            DB::commit();

            $message = "Copied {$results['grading_rules']} grading rules and {$results['division_rules']} division rules successfully.";

            return back()->with('success', $message);

        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withErrors(['error' => 'Failed to copy rules: ' . $e->getMessage()]);
        }
    }

    /**
     * Create default rules for academic year
     */
    public function createDefaultRules(Request $request): RedirectResponse
    {
        $this->authorize('create', GradingRule::class);
        $this->authorize('create', DivisionRule::class);

        $validated = $request->validate([
            'academic_year_id' => 'required|exists:academic_years,id',
        ]);

        try {
            DB::beginTransaction();

            $results = $this->configurationService->createDefaultRules($validated['academic_year_id']);

            DB::commit();

            $message = "Created {$results['grading_rules']} grading rules and {$results['division_rules']} division rules successfully.";

            return back()->with('success', $message);

        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withErrors(['error' => 'Failed to create default rules: ' . $e->getMessage()]);
        }
    }

    /**
     * Get rules for specific academic year (API endpoint)
     */
    public function getRulesForAcademicYear(Request $request): \Illuminate\Http\JsonResponse
    {
        $request->validate([
            'academic_year_id' => 'required|exists:academic_years,id',
        ]);

        $gradingRules = GradingRule::getRulesForAcademicYear($request->academic_year_id);
        $divisionRules = DivisionRule::getRulesForAcademicYear($request->academic_year_id);

        return response()->json([
            'grading_rules' => $gradingRules,
            'division_rules' => $divisionRules,
        ]);
    }

    /**
     * Bulk import rules from CSV
     */
    public function importRules(Request $request): RedirectResponse
    {
        $this->authorize('create', GradingRule::class);

        $request->validate([
            'academic_year_id' => 'required|exists:academic_years,id',
            'rule_type' => 'required|in:grading,division',
            'csv_file' => 'required|file|mimes:csv,txt|max:2048',
        ]);

        try {
            DB::beginTransaction();

            $file = $request->file('csv_file');
            $csvData = array_map('str_getcsv', file($file->path()));
            $headers = array_shift($csvData);

            $successCount = 0;
            $errors = [];

            foreach ($csvData as $index => $row) {
                try {
                    $data = array_combine($headers, $row);
                    $data['academic_year_id'] = $request->academic_year_id;

                    if ($request->rule_type === 'grading') {
                        $this->configurationService->createGradingRule($data);
                    } else {
                        $this->configurationService->createDivisionRule($data);
                    }

                    $successCount++;

                } catch (\Exception $e) {
                    $errors[] = "Row " . ($index + 2) . ": " . $e->getMessage();
                }
            }

            DB::commit();

            $message = "{$successCount} rules imported successfully.";
            if (!empty($errors)) {
                $message .= " " . count($errors) . " errors occurred.";
            }

            return back()
                ->with('success', $message)
                ->with('import_errors', $errors);

        } catch (\Exception $e) {
            DB::rollBack();

            return back()
                ->withErrors(['error' => 'Import failed: ' . $e->getMessage()]);
        }
    }
}
