<?php

namespace App\Http\Controllers\Modules\Employee;

use App\Http\Controllers\Controller;
use App\Http\Traits\HasRoleViews;
use App\Models\EmployeeDetails;
use App\Models\EmployeeSalaryStructure;
use App\Services\Employee\SalaryStructureService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\Alignment;

/**
 * Unified Salary Structure Controller
 *
 * Handles employee salary structure management for all roles.
 * Reference: SuperAdminSalaryStructureController
 */
class SalaryStructureController extends Controller
{
    use HasRoleViews;

    protected SalaryStructureService $salaryStructureService;

    public function __construct(SalaryStructureService $salaryStructureService)
    {
        $this->salaryStructureService = $salaryStructureService;
    }

    /**
     * Display the salary structure page
     */
    public function index()
    {
        $employees = EmployeeDetails::select('id', 'employee_id', 'name', 'designation', 'department')
            ->where('status', EmployeeDetails::STATUS_ACTIVE)
            ->get();

        $structures = $this->salaryStructureService->getAllWithEmployee();
        $stats = $this->salaryStructureService->getSummaryStats();
        $employeesWithoutStructure = $this->salaryStructureService->getEmployeesWithoutStructure();

        return $this->roleView('employee.salary_structure', compact(
            'employees',
            'structures',
            'stats',
            'employeesWithoutStructure'
        ));
    }

    /**
     * Store or update salary structure
     */
    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'employee_id' => 'required|exists:employees,id',
            'basic_da' => 'nullable|numeric|min:0',
            'hra' => 'nullable|numeric|min:0',
            'conveyance' => 'nullable|numeric|min:0',
            'washing_allowance' => 'nullable|numeric|min:0',
            'incentive_per_hour' => 'nullable|numeric|min:0',
            'fixed_salary' => 'nullable|numeric|min:0',
            'pf_percentage' => 'nullable|numeric|between:0,100',
            'esi_percentage' => 'nullable|numeric|between:0,100',
            'pt_percentage' => 'nullable|numeric|between:0,100',
            'effective_from' => 'nullable|date',
        ]);

        try {
            // Check if structure exists
            $existing = $this->salaryStructureService->getByEmployee($validated['employee_id']);

            if ($existing) {
                // Revise existing structure
                $structure = $this->salaryStructureService->reviseStructure(
                    $validated['employee_id'],
                    $validated
                );
            } else {
                // Create new structure
                $structure = $this->salaryStructureService->createStructure($validated);
            }

            return response()->json([
                'success' => true,
                'message' => 'Salary Structure saved successfully.',
                'data' => $structure,
            ]);
        } catch (\Exception $e) {
            Log::error('Failed to save salary structure: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to save salary structure: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Get salary structure for an employee (AJAX)
     */
    public function getStructure(int $employeeId): JsonResponse
    {
        $structure = $this->salaryStructureService->getActiveForEmployee($employeeId);

        if (!$structure) {
            return response()->json([
                'success' => false,
                'message' => 'No active salary structure found',
            ]);
        }

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

    /**
     * Get salary breakdown for an employee
     */
    public function getBreakdown(int $employeeId): JsonResponse
    {
        $breakdown = $this->salaryStructureService->getSalaryBreakdown($employeeId);

        if (!$breakdown) {
            return response()->json([
                'success' => false,
                'message' => 'No salary structure found for this employee',
            ]);
        }

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

    /**
     * Deactivate a salary structure
     */
    public function deactivate(int $id): JsonResponse
    {
        try {
            $this->salaryStructureService->deactivate($id);

            return response()->json([
                'success' => true,
                'message' => 'Salary structure deactivated successfully',
            ]);
        } catch (\Exception $e) {
            Log::error('Failed to deactivate salary structure: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to deactivate salary structure',
            ], 500);
        }
    }

    /**
     * Import salary structures from Excel
     */
    public function import(Request $request)
    {
        $request->validate([
            'import_file' => 'required|file|mimes:xlsx,xls',
        ]);

        $file = $request->file('import_file');

        try {
            $spreadsheet = IOFactory::load($file->getPathname());
            $sheet = $spreadsheet->getActiveSheet();
            $rows = $sheet->toArray();

            $structures = [];
            $skipped = 0;
            $parseErrors = [];

            foreach ($rows as $index => $row) {
                if ($index === 0) continue; // Skip header
                if (empty($row[0])) continue;

                $employeeCode = trim($row[0]);
                $employee = EmployeeDetails::where('employee_id', $employeeCode)->first();

                if (!$employee) {
                    $skipped++;
                    $parseErrors[] = "Row " . ($index + 1) . ": Employee ID '$employeeCode' not found";
                    continue;
                }

                // Parse values with defaults
                $basicDa = is_numeric($row[1] ?? '') ? floatval($row[1]) : 0;
                $hra = is_numeric($row[2] ?? '') ? floatval($row[2]) : 0;
                $conveyance = is_numeric($row[3] ?? '') ? floatval($row[3]) : 0;
                $washingAllowance = is_numeric($row[4] ?? '') ? floatval($row[4]) : 0;
                $incentivePerHour = is_numeric($row[5] ?? '') ? floatval($row[5]) : 0;
                $fixedSalary = is_numeric($row[6] ?? '') ? floatval($row[6]) : 0;
                $pfPercentage = is_numeric($row[7] ?? '') ? floatval($row[7]) : null;
                $esiPercentage = is_numeric($row[8] ?? '') ? floatval($row[8]) : null;
                $ptPercentage = is_numeric($row[9] ?? '') ? floatval($row[9]) : null;

                // Auto-calculate fixed salary if not provided
                if ($fixedSalary == 0) {
                    $fixedSalary = $basicDa + $hra + $conveyance + $washingAllowance;
                }

                $structures[] = [
                    'employee_id' => $employee->id,
                    'basic_da' => $basicDa,
                    'hra' => $hra,
                    'conveyance' => $conveyance,
                    'washing_allowance' => $washingAllowance,
                    'incentive_per_hour' => $incentivePerHour,
                    'fixed_salary' => $fixedSalary,
                    'pf_percentage' => $pfPercentage,
                    'esi_percentage' => $esiPercentage,
                    'pt_percentage' => $ptPercentage,
                ];
            }

            // Use service to import structures
            $results = $this->salaryStructureService->importStructures($structures);

            $message = "Successfully imported {$results['success']} salary structure(s).";
            if ($results['failed'] > 0 || $skipped > 0) {
                $totalFailed = $results['failed'] + $skipped;
                $message .= " Failed/Skipped: $totalFailed row(s).";
            }

            $allErrors = array_merge($parseErrors, $results['errors']);
            if (!empty($allErrors)) {
                Log::warning('Salary structure import errors:', $allErrors);
            }

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

        } catch (\Exception $e) {
            Log::error('Salary structure import error: ' . $e->getMessage());
            return back()->with('error', 'Failed to import file: ' . $e->getMessage());
        }
    }

    /**
     * Download sample Excel file for import
     */
    public function downloadSample()
    {
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setTitle('Salary Structure');

        // Set headers
        $headers = [
            'Employee ID',
            'Basic & DA',
            'HRA',
            'Conveyance',
            'Washing Allowance',
            'Incentive per Hour',
            'Fixed Salary',
            'PF %',
            'ESI %',
            'PT %',
        ];

        $sheet->fromArray($headers, null, 'A1');

        // Style header row
        $headerStyle = [
            'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
            'fill' => [
                'fillType' => Fill::FILL_SOLID,
                'startColor' => ['rgb' => '4472C4'],
            ],
            'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
        ];
        $sheet->getStyle('A1:J1')->applyFromArray($headerStyle);

        // Add sample data
        $sampleData = [
            ['1001', 15000, 5000, 2000, 500, 50, 22500, 12, 0.75, 2.5],
            ['1002', 18000, 6000, 2500, 600, 60, 27100, 12, 0.75, 2.5],
            ['1003', 20000, 7000, 3000, 700, 75, 30700, 12, 0.75, 2.5],
        ];

        $sheet->fromArray($sampleData, null, 'A2');

        // Auto-size columns
        foreach (range('A', 'J') as $col) {
            $sheet->getColumnDimension($col)->setAutoSize(true);
        }

        // Add instructions sheet
        $instructionSheet = $spreadsheet->createSheet();
        $instructionSheet->setTitle('Instructions');

        $instructions = [
            ['Salary Structure Import Instructions'],
            [''],
            ['Column', 'Description', 'Required', 'Example'],
            ['Employee ID', 'Must match existing Employee ID in system', 'Yes', '1001'],
            ['Basic & DA', 'Basic salary + DA amount', 'No', '15000'],
            ['HRA', 'House Rent Allowance', 'No', '5000'],
            ['Conveyance', 'Conveyance Allowance', 'No', '2000'],
            ['Washing Allowance', 'Washing Allowance', 'No', '500'],
            ['Incentive per Hour', 'Hourly incentive rate', 'No', '50'],
            ['Fixed Salary', 'Total fixed salary (auto-calculated if empty)', 'No', '22500'],
            ['PF %', 'Provident Fund percentage (0-100)', 'No', '12'],
            ['ESI %', 'ESI percentage (0-100)', 'No', '0.75'],
            ['PT %', 'Professional Tax percentage (0-100)', 'No', '2.5'],
            [''],
            ['Notes:'],
            ['1. First row is header - do not modify'],
            ['2. Employee ID must exist in the system'],
            ['3. If Fixed Salary is empty/0, it will be auto-calculated'],
            ['4. Existing structures will be updated if Employee ID already exists'],
        ];

        $instructionSheet->fromArray($instructions, null, 'A1');
        $instructionSheet->getStyle('A1')->getFont()->setBold(true)->setSize(14);
        $instructionSheet->getStyle('A3:D3')->getFont()->setBold(true);

        foreach (range('A', 'D') as $col) {
            $instructionSheet->getColumnDimension($col)->setAutoSize(true);
        }

        // Set active sheet back to data sheet
        $spreadsheet->setActiveSheetIndex(0);

        // Create response
        $fileName = 'salary_structure_sample.xlsx';
        $writer = new Xlsx($spreadsheet);

        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $fileName . '"');
        header('Cache-Control: max-age=0');

        $writer->save('php://output');
        exit;
    }
}
