<?php

declare(strict_types=1);

namespace App\Services;

use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Concerns\WithTitle;
use Maatwebsite\Excel\Facades\Excel;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

/**
 * 범용 엑셀 내보내기 서비스
 *
 * 여러 모듈에서 공통으로 사용할 수 있는 엑셀 내보내기 기능 제공
 * - 근태관리 (AttendanceController)
 * - 급여관리 (SalaryController)
 * - 기타 데이터 내보내기가 필요한 모듈
 */
class ExportService extends Service
{
    /**
     * 엑셀 파일 다운로드
     *
     * @param  array<int, array<string, mixed>>  $data  내보낼 데이터 배열
     * @param  array<int, string>  $headings  컬럼 헤더 배열
     * @param  string  $filename  다운로드 파일명 (확장자 제외)
     * @param  string  $sheetTitle  시트 제목
     */
    public function download(
        array $data,
        array $headings,
        string $filename,
        string $sheetTitle = 'Sheet1'
    ): BinaryFileResponse {
        $export = new GenericExport($data, $headings, $sheetTitle);

        return Excel::download($export, $filename.'.xlsx');
    }

    /**
     * 엑셀 파일 저장 (서버에 저장)
     *
     * @param  array<int, array<string, mixed>>  $data  내보낼 데이터 배열
     * @param  array<int, string>  $headings  컬럼 헤더 배열
     * @param  string  $path  저장 경로 (storage/app 기준)
     * @param  string  $sheetTitle  시트 제목
     */
    public function store(
        array $data,
        array $headings,
        string $path,
        string $sheetTitle = 'Sheet1'
    ): bool {
        $export = new GenericExport($data, $headings, $sheetTitle);

        return Excel::store($export, $path);
    }
}

/**
 * 범용 엑셀 내보내기 클래스
 *
 * ExportService에서 내부적으로 사용하는 Maatwebsite Excel 구현체
 */
class GenericExport implements FromArray, ShouldAutoSize, WithHeadings, WithStyles, WithTitle
{
    /**
     * @param  array<int, array<string, mixed>>  $data  내보낼 데이터
     * @param  array<int, string>  $headings  컬럼 헤더
     * @param  string  $sheetTitle  시트 제목
     */
    public function __construct(
        private readonly array $data,
        private readonly array $headings,
        private readonly string $sheetTitle
    ) {}

    /**
     * 데이터 배열 반환
     *
     * @return array<int, array<string, mixed>>
     */
    public function array(): array
    {
        return $this->data;
    }

    /**
     * 헤더 배열 반환
     *
     * @return array<int, string>
     */
    public function headings(): array
    {
        return $this->headings;
    }

    /**
     * 시트 제목 반환
     */
    public function title(): string
    {
        return $this->sheetTitle;
    }

    /**
     * 스타일 적용
     *
     * @return array<int|string, array<string, mixed>>
     */
    public function styles(Worksheet $sheet): array
    {
        return [
            // 헤더 행 스타일 (굵게, 배경색)
            1 => [
                'font' => ['bold' => true],
                'fill' => [
                    'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
                    'startColor' => ['rgb' => 'E2E8F0'],
                ],
            ],
        ];
    }
}
