<?php

namespace App\Http\Controllers;

use App\Models\SystemSetting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class SettingsController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    /* -------------------- BUSINESS SETTINGS -------------------- */

    public function business()
    {
        $keys = [
            'business_name','trade_license','bin','tin',
            'company_email','phone','website','address',
            'number_format',
            'business_logo',
        ];

        $settings = $this->getMany($keys);
        return view('settings.business', compact('settings'));
    }

    public function businessSave(Request $request)
    {
        $data = $request->validate([
            'business_name'  => ['required','string','max:190'],
            'trade_license'  => ['nullable','string','max:190'],
            'bin'            => ['nullable','string','max:190'],
            'tin'            => ['nullable','string','max:190'],
            'company_email'  => ['nullable','email','max:190'],
            'phone'          => ['nullable','string','max:190'],
            'website'        => ['nullable','string','max:190'],
            'address'        => ['nullable','string','max:2000'],
            'number_format'  => ['required','in:indian,international,intl'], // allow intl alias
            'business_logo'  => ['nullable','image','mimes:png,jpg,jpeg,webp','max:2048'],
        ]);

        if ($request->hasFile('business_logo')) {
            $path = $request->file('business_logo')->store('public/settings');
            $data['business_logo'] = Storage::url($path);
        }

        // normalize intl alias
        if (($data['number_format'] ?? '') === 'international') {
            $data['number_format'] = 'intl';
        }

        $this->putMany($data);

        return back()->with('success', 'Business settings updated.');
    }

    /* -------------------- INVOICE SETTINGS -------------------- */

    public function invoice()
    {
        $keys = [
            'invoice_prefix','invoice_pad','invoice_next',
            'currency_position','date_format',
            'paper_size','orientation',
            'margin_top','margin_right','margin_bottom','margin_left',
            'default_vat',
            'copies_office','copies_customer',

            'show_logo','show_header','show_footer',
            'show_qr','show_barcode','show_signature','show_paid_stamp',

            'header_note','footer_note','terms',
            'invoice_logo',
        ];

        $settings = $this->getMany($keys);
        return view('settings.invoice', compact('settings'));
    }

    public function invoiceSave(Request $request)
    {
        $data = $request->validate([
            'invoice_prefix'   => ['nullable','string','max:30'],
            'invoice_pad'      => ['nullable','integer','min:1','max:12'],
            'invoice_next'     => ['nullable','integer','min:1'],

            'currency_position'=> ['required','in:left,left_space,right,right_space'],
            'date_format'      => ['required','string','max:30'],

            'paper_size'       => ['required','in:A4,A5,POS80'],
            'orientation'      => ['required','in:portrait,landscape'],

            'margin_top'       => ['nullable','numeric','min:0','max:100'],
            'margin_right'     => ['nullable','numeric','min:0','max:100'],
            'margin_bottom'    => ['nullable','numeric','min:0','max:100'],
            'margin_left'      => ['nullable','numeric','min:0','max:100'],

            'default_vat'      => ['nullable','numeric','min:0','max:100'],

            'copies_office'    => ['nullable','integer','min:0','max:10'],
            'copies_customer'  => ['nullable','integer','min:0','max:10'],

            'show_logo'        => ['nullable','boolean'],
            'show_header'      => ['nullable','boolean'],
            'show_footer'      => ['nullable','boolean'],
            'show_qr'          => ['nullable','boolean'],
            'show_barcode'     => ['nullable','boolean'],
            'show_signature'   => ['nullable','boolean'],
            'show_paid_stamp'  => ['nullable','boolean'],

            'header_note'      => ['nullable','string'],
            'footer_note'      => ['nullable','string'],
            'terms'            => ['nullable','string'],

            'invoice_logo'     => ['nullable','image','mimes:png,jpg,jpeg,webp','max:2048'],
        ]);

        foreach ([
            'show_logo','show_header','show_footer',
            'show_qr','show_barcode','show_signature','show_paid_stamp'
        ] as $flag) {
            $data[$flag] = $request->boolean($flag) ? 1 : 0;
        }

        if ($request->hasFile('invoice_logo')) {
            $path = $request->file('invoice_logo')->store('public/settings');
            $data['invoice_logo'] = Storage::url($path);
        }

        $this->putMany($data);

        return back()->with('success', 'Invoice settings updated.');
    }

    /* -------------------- PRINTERS SETTINGS -------------------- */

    public function printers()
    {
        $keys = [
            'print_driver','default_printer','print_copies','show_print_dialog',
            'paper_size','print_alignment',
            'pos_width','pos_chars','pos_cut','pos_drawer','pos_logo','pos_qr',
            'pos_left','pos_right','pos_top','pos_bottom',
        ];
        $settings = $this->getMany($keys);
        return view('settings.printers', compact('settings'));
    }

    public function printersSave(Request $r)
    {
        $data = $r->validate([
            'print_driver'     => ['required','in:browser,system,escpos'],
            'default_printer'  => ['nullable','string','max:190'],
            'print_copies'     => ['nullable','integer','min:1','max:10'],
            'show_print_dialog'=> ['nullable','boolean'],

            'paper_size'       => ['required','in:A4,A5,POS80,POS58'],
            'print_alignment'  => ['required','in:left,center,right'],

            'pos_width'        => ['nullable','in:80,58'],
            'pos_chars'        => ['nullable','integer','min:24','max:64'],
            'pos_cut'          => ['nullable','boolean'],
            'pos_drawer'       => ['nullable','boolean'],
            'pos_logo'         => ['nullable','boolean'],
            'pos_qr'           => ['nullable','boolean'],
            'pos_left'         => ['nullable','numeric','min:0','max:20'],
            'pos_right'        => ['nullable','numeric','min:0','max:20'],
            'pos_top'          => ['nullable','numeric','min:0','max:30'],
            'pos_bottom'       => ['nullable','numeric','min:0','max:30'],
        ]);

        foreach (['show_print_dialog','pos_cut','pos_drawer','pos_logo','pos_qr'] as $flag) {
            $data[$flag] = $r->boolean($flag) ? 1 : 0;
        }

        $this->putMany($data);
        return back()->with('success','Printer settings updated.');
    }

    public function currencies()
{
    $keys = ['currencies','default_currency'];
    $settings = $this->getMany($keys);
    return view('settings.currencies', compact('settings'));
}

public function currenciesSave(Request $r)
{
    $rows = $r->input('currencies', []);
    if (!is_array($rows)) $rows = [];

    $clean = [];
    $codes = [];

    foreach ($rows as $i => $row) {
        $name = trim($row['name'] ?? '');
        $code = strtoupper(trim($row['code'] ?? ''));

        if ($name === '' || $code === '' || strlen($code) !== 3) {
            continue;
        }

        // ensure unique 3-letter codes
        $base = $code;
        $suffix = 1;
        while (in_array($code, $codes, true)) {
            $code = substr($base,0,2) . ($suffix++);
        }
        $codes[] = $code;

        $symbol   = trim($row['symbol'] ?? '');
        $position = in_array(($row['position'] ?? ''), ['left','left_space','right','right_space'], true)
                    ? $row['position'] : 'left';

        $decimals = is_numeric($row['decimals'] ?? null) ? max(0, min(4, (int)$row['decimals'])) : 2;

        $thousand = $row['thousand_sep'] ?? ',';
        if (!in_array($thousand, [',','.',' ','_','none'], true)) $thousand = ',';

        $decimal = $row['decimal_sep'] ?? '.';
        if (!in_array($decimal, ['.',','], true)) $decimal = '.';

        $rate   = is_numeric($row['rate'] ?? null) ? (float)$row['rate'] : 1.0;
        if ($rate <= 0) $rate = 1.0;

        $order  = is_numeric($row['order'] ?? null) ? (int)$row['order'] : ($i+1);
        $notes  = trim($row['notes'] ?? '');

        $clean[] = [
            'active'       => !empty($row['active']) ? 1 : 0,
            'name'         => $name,
            'code'         => $code,
            'symbol'       => $symbol,
            'position'     => $position,
            'decimals'     => $decimals,
            'thousand_sep' => $thousand,
            'decimal_sep'  => $decimal,
            'rate'         => $rate,
            'order'        => $order,
            'notes'        => $notes,
        ];
    }

    // sort by order
    usort($clean, fn($a,$b)=>($a['order'] <=> $b['order']));

    // determine default/base currency
    $reqDefault = strtoupper(trim($r->input('default_currency','')));
    $available  = array_column($clean, 'code');

    if ($reqDefault !== '' && in_array($reqDefault, $available, true)) {
        $default = $reqDefault;
    } else {
        $firstActive = collect($clean)->firstWhere('active', 1);
        $default = $firstActive['code'] ?? ($available[0] ?? 'BDT');
    }

    // base rate = 1.0
    foreach ($clean as &$c) {
        if ($c['code'] === $default) {
            $c['rate'] = 1.0;
        }
    }

    $this->putMany([
        'currencies'       => json_encode($clean),
        'default_currency' => $default,
    ]);

    return back()->with('success','Currency settings updated.');
}

    /* -------------------- PAYMENTS SETTINGS (NEW) -------------------- */

    public function payments()
    {
        $keys = ['payment_methods','default_payment_method'];
        $settings = $this->getMany($keys);

        // decode JSON to array if you prefer, but Blade already handles both patterns
        // $raw = $settings['payment_methods'] ?? null;
        // $settings['payment_methods'] = is_string($raw) ? json_decode($raw, true) : $raw;

        return view('settings.payments', compact('settings'));
    }

    public function paymentsSave(Request $r)
    {
        // We’ll sanitize dynamic rows manually
        $rows = $r->input('methods', []);
        if (!is_array($rows)) $rows = [];

        $clean  = [];
        $codes  = [];

        foreach ($rows as $i => $row) {
            $name = trim($row['name'] ?? '');
            $code = trim($row['code'] ?? '');

            if ($name === '' || $code === '') {
                continue; // skip invalid rows
            }

            // make code URL/slug safe but allow underscore
            $code = Str::slug($code, '_');
            if ($code === '') {
                continue;
            }

            // ensure unique codes
            $base = $code;
            $suffix = 1;
            while (in_array($code, $codes, true)) {
                $code = $base . '_' . $suffix++;
            }
            $codes[] = $code;

            $type      = in_array(($row['type'] ?? ''), ['cash','bank','card','mobile','other'], true)
                        ? $row['type'] : 'other';
            $fee_type  = in_array(($row['fee_type'] ?? ''), ['none','percent','fixed'], true)
                        ? $row['fee_type'] : 'none';
            $fee_value = is_numeric($row['fee_value'] ?? null) ? (float)$row['fee_value'] : 0;

            $active = !empty($row['active']) ? 1 : 0;
            $pos    = !empty($row['pos'])    ? 1 : 0;
            $web    = !empty($row['web'])    ? 1 : 0;

            $order  = is_numeric($row['order'] ?? null) ? (int)$row['order'] : ($i+1);
            $notes  = trim($row['notes'] ?? '');

            $clean[] = [
                'active'    => $active,
                'name'      => $name,
                'code'      => $code,
                'type'      => $type,
                'fee_type'  => $fee_type,
                'fee_value' => $fee_value,
                'pos'       => $pos,
                'web'       => $web,
                'order'     => $order,
                'notes'     => $notes,
            ];
        }

        // sort by order asc
        usort($clean, fn($a,$b) => ($a['order'] <=> $b['order']));

        // default method
        $reqDefault = trim($r->input('default_payment_method',''));
        $available  = array_column($clean, 'code');
        if ($reqDefault !== '' && in_array($reqDefault, $available, true)) {
            $default = $reqDefault;
        } else {
            // try first active, else first
            $firstActive = collect($clean)->firstWhere('active', 1);
            $default = $firstActive['code'] ?? ($available[0] ?? 'cash');
        }

        $this->putMany([
            'payment_methods'         => json_encode($clean),
            'default_payment_method'  => $default,
        ]);

        return back()->with('success', 'Payment methods updated.');
    }

    /* -------------------- UTILITIES -------------------- */

    protected function getMany(array $keys): array
    {
        $rows = SystemSetting::query()
            ->whereIn('key', $keys)
            ->pluck('value', 'key')
            ->toArray();

        foreach ($keys as $k) {
            if (!array_key_exists($k, $rows)) {
                $rows[$k] = null;
            }
        }
        return $rows;
    }

    protected function putMany(array $pairs): void
    {
        foreach ($pairs as $key => $value) {
            SystemSetting::updateOrCreate(
                ['key' => $key],
                ['value' => is_array($value) ? json_encode($value) : (string) $value]
            );
        }
    }
}

