<?php

namespace App\Controllers\Admin;

use App\Controllers\BaseController;
use App\Models\TamuModel;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Throwable;

class Tamu extends BaseController
{
    public function index()
    {
        return view('admin/tamu/index', $this->data + [
            'title' => 'Tamu Undangan',
            'items' => (new TamuModel())->orderBy('id', 'DESC')->findAll(),
        ]);
    }

    public function new()
    {
        return view('admin/tamu/form', $this->data + ['title' => 'Tambah Tamu', 'item' => null]);
    }

    public function create()
    {
        if (! $this->validate($this->rules())) {
            return redirect()->back()->withInput()->with('error', implode(' ', $this->validator->getErrors()));
        }
        $name = trim((string) $this->request->getPost('nama_tamu'));
        (new TamuModel())->insert([
            'nama_tamu' => $name,
            'slug' => $this->uniqueSlug($name),
            'nomor_hp' => $this->normalizePhoneInput((string) $this->request->getPost('nomor_hp')),
            'status_kehadiran' => $this->request->getPost('status_kehadiran') ?: 'belum',
        ]);

        return redirect()->to('/admin/tamu')->with('success', 'Tamu berhasil ditambahkan.');
    }

    public function edit($id = null)
    {
        $item = (new TamuModel())->find($id);
        if (! $item) {
            return redirect()->to('/admin/tamu')->with('error', 'Data tamu tidak ditemukan.');
        }
        return view('admin/tamu/form', $this->data + ['title' => 'Edit Tamu', 'item' => $item]);
    }

    public function update($id = null)
    {
        $model = new TamuModel();
        if (! $model->find($id)) {
            return redirect()->to('/admin/tamu')->with('error', 'Data tamu tidak ditemukan.');
        }
        if (! $this->validate($this->rules())) {
            return redirect()->back()->withInput()->with('error', implode(' ', $this->validator->getErrors()));
        }
        $name = trim((string) $this->request->getPost('nama_tamu'));
        $model->update($id, [
            'nama_tamu' => $name,
            'slug' => $this->uniqueSlug($name, (int) $id),
            'nomor_hp' => $this->normalizePhoneInput((string) $this->request->getPost('nomor_hp')),
            'status_kehadiran' => $this->request->getPost('status_kehadiran'),
        ]);

        return redirect()->to('/admin/tamu')->with('success', 'Tamu berhasil diperbarui.');
    }

    public function delete($id = null)
    {
        $model = new TamuModel();
        if (! $model->find($id)) {
            return redirect()->back()->with('error', 'Data tamu tidak ditemukan.');
        }
        $model->delete($id);
        return redirect()->back()->with('success', 'Tamu dihapus.');
    }

    public function import()
    {
        $file = $this->request->getFile('file_excel');
        if (! $file || ! $file->isValid() || $file->getSize() > 5 * 1024 * 1024) {
            return redirect()->back()->with('error', 'File Excel tidak valid atau melebihi 5 MB.');
        }
        if (! in_array(strtolower($file->getClientExtension()), ['xlsx', 'xls', 'csv'], true)) {
            return redirect()->back()->with('error', 'Format file harus XLSX, XLS, atau CSV.');
        }

        try {
            $rows = IOFactory::load($file->getTempName())->getActiveSheet()->toArray();
        } catch (Throwable) {
            return redirect()->back()->with('error', 'File tidak dapat dibaca. Pastikan format spreadsheet tidak rusak.');
        }

        $model = new TamuModel();
        $count = 0;
        foreach (array_slice($rows, 1) as $row) {
            $name = trim((string) ($row[0] ?? ''));
            if ($name === '') {
                continue;
            }
            $model->insert([
                'nama_tamu' => mb_substr($name, 0, 180),
                'slug' => $this->uniqueSlug($name),
                'nomor_hp' => $this->normalizePhoneInput((string) ($row[1] ?? '')),
                'status_kehadiran' => 'belum',
            ]);
            $count++;
        }

        return redirect()->back()->with($count ? 'success' : 'error', $count ? "$count data tamu berhasil diimpor." : 'Tidak ada data tamu yang dapat diimpor.');
    }

    public function export()
    {
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->fromArray(['Nama Tamu', 'Nomor HP', 'Link Undangan', 'Status Kehadiran'], null, 'A1');
        $sheet->getStyle('A1:D1')->getFont()->setBold(true);
        $sheet->getColumnDimension('A')->setWidth(32);
        $sheet->getColumnDimension('B')->setWidth(20);
        $sheet->getColumnDimension('C')->setWidth(60);
        $sheet->getColumnDimension('D')->setWidth(20);

        $row = 2;
        foreach ((new TamuModel())->findAll() as $item) {
            $sheet->fromArray([
                $item['nama_tamu'],
                $item['nomor_hp'],
                base_url('u/' . $item['slug']),
                ucwords(str_replace('_', ' ', $item['status_kehadiran'])),
            ], null, 'A' . $row++);
        }

        $path = WRITEPATH . 'cache/tamu-undangan-' . date('Ymd-His') . '.xlsx';
        (new Xlsx($spreadsheet))->save($path);
        return $this->response->download($path, null)->setFileName('tamu-undangan.xlsx');
    }

    private function rules(): array
    {
        return [
            'nama_tamu' => 'required|min_length[2]|max_length[180]',
            'nomor_hp' => 'permit_empty|max_length[30]|regex_match[/^[0-9+() .-]+$/]',
            'status_kehadiran' => 'required|in_list[belum,hadir,tidak_hadir]',
        ];
    }

    private function normalizePhoneInput(string $phone): ?string
    {
        $phone = trim($phone);
        return $phone === '' ? null : mb_substr($phone, 0, 30);
    }

    private function uniqueSlug(string $name, int $ignore = 0): string
    {
        $base = url_title($name, '-', true) ?: 'tamu';
        $slug = $base;
        $suffix = 2;
        $model = new TamuModel();
        while ($model->where('slug', $slug)->where('id !=', $ignore)->first()) {
            $slug = $base . '-' . $suffix++;
        }
        return $slug;
    }
}
