<?php

namespace App\Http\Controllers\Company\Admin;

use App\Http\Controllers\Controller;
use App\Models\{AuditLog, VoucherNumberSetting};
use App\Services\VoucherNumberService;
use Illuminate\Http\Request;

class VoucherNumberingController extends Controller
{
    public function index()
    {
        $this->authorize_permission('settings', 'view');

        $voucherTypes = VoucherNumberService::voucherTypes();
        $companyId    = auth()->user()->company_id;

        $settings = VoucherNumberSetting::withoutGlobalScopes()->where('company_id', $companyId)->get()->keyBy('voucher_type');

        // Merge with defaults for types not yet configured
        $merged = [];
        foreach ($voucherTypes as $type => $label) {
            $merged[$type] = [
                'label'   => $label,
                'setting' => $settings->get($type),
                'preview' => VoucherNumberService::preview($companyId, $type),
            ];
        }

        return view('admin.voucher-numbering.index', compact('merged'));
    }

    public function edit(string $voucherType)
    {
        $this->authorize_permission('settings', 'edit');

        $voucherTypes = VoucherNumberService::voucherTypes();
        if (!array_key_exists($voucherType, $voucherTypes)) {
            abort(404, 'Unknown voucher type.');
        }

        $companyId = auth()->user()->company_id;
        $setting   = VoucherNumberSetting::firstOrCreate(
            ['company_id' => $companyId, 'voucher_type' => $voucherType],
            [
                'prefix'           => strtoupper(substr($voucherType, 0, 3)),
                'starting_number'  => 1,
                'current_number'   => 0,
                'padding_digits'   => 4,
                'separator'        => '-',
                'include_year'     => false,
                'include_month'    => false,
                'reset_period'     => 'never',
                'number_on'        => 'draft',
                'allow_manual'     => false,
            ]
        );

        $label   = $voucherTypes[$voucherType];
        $preview = VoucherNumberService::preview($companyId, $voucherType);

        return view('admin.voucher-numbering.edit', compact('setting', 'label', 'voucherType', 'preview'));
    }

    public function update(Request $request, string $voucherType)
    {
        $this->authorize_permission('settings', 'edit');

        $voucherTypes = VoucherNumberService::voucherTypes();
        if (!array_key_exists($voucherType, $voucherTypes)) {
            abort(404);
        }

        $validated = $request->validate([
            'prefix'          => 'nullable|string|max:20|alpha_num',
            'suffix'          => 'nullable|string|max:20|alpha_num',
            'starting_number' => 'required|integer|min:1',
            'padding_digits'  => 'required|integer|min:1|max:10',
            'separator'       => 'nullable|string|max:3',
            'include_year'    => 'boolean',
            'include_month'   => 'boolean',
            'reset_period'    => 'required|in:never,yearly,monthly',
            'number_on'       => 'required|in:draft,approval',
            'allow_manual'    => 'boolean',
        ]);

        $companyId = auth()->user()->company_id;

        $setting = VoucherNumberSetting::withoutGlobalScopes()
            ->where('company_id', $companyId)
            ->where('voucher_type', $voucherType)
            ->first();

        $old = $setting ? $setting->toArray() : [];

        VoucherNumberSetting::withoutGlobalScopes()->updateOrCreate(
            ['company_id' => $companyId, 'voucher_type' => $voucherType],
            [
                'prefix'          => $validated['prefix'] ?? null,
                'suffix'          => $validated['suffix'] ?? null,
                'starting_number' => $validated['starting_number'],
                'padding_digits'  => $validated['padding_digits'],
                'separator'       => $validated['separator'] ?? '-',
                'include_year'    => $request->boolean('include_year'),
                'include_month'   => $request->boolean('include_month'),
                'reset_period'    => $validated['reset_period'],
                'number_on'       => $validated['number_on'],
                'allow_manual'    => $request->boolean('allow_manual'),
            ]
        );

        AuditLog::record('update', 'voucher_numbering', null, $old, $validated,
            "Voucher numbering updated: {$voucherType}");

        return redirect()->route('admin.voucher-numbering.index')
            ->with('success', "Voucher numbering for '{$voucherTypes[$voucherType]}' saved.");
    }

    public function previewAjax(Request $request)
    {
        $request->validate([
            'prefix'         => 'nullable|string|max:20',
            'suffix'         => 'nullable|string|max:20',
            'starting_number'=> 'required|integer|min:1',
            'padding_digits' => 'required|integer|min:1|max:10',
            'separator'      => 'nullable|string|max:3',
            'include_year'   => 'boolean',
            'include_month'  => 'boolean',
            'current_number' => 'nullable|integer|min:0',
        ]);

        $parts  = [];
        $sep    = $request->input('separator', '-');
        $next   = max((int) $request->input('current_number', 0) + 1, (int) $request->input('starting_number', 1));

        if ($request->prefix)                 $parts[] = $request->prefix;
        if ($request->boolean('include_year')) $parts[] = now()->format('Y');
        if ($request->boolean('include_month'))$parts[] = now()->format('m');

        $parts[] = str_pad($next, (int) $request->input('padding_digits', 4), '0', STR_PAD_LEFT);

        if ($request->suffix) $parts[] = $request->suffix;

        return response()->json(['preview' => implode($sep ?: '-', $parts)]);
    }

    private function authorize_permission(string $module, string $action): void
    {
        if (!auth()->user()->hasPermission($module, $action)) {
            abort(403);
        }
    }
}
