<?php

namespace App\Http\Controllers\Admin\Voucher;

use App\Http\Controllers\Controller;
use App\Models\Voucher;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Inertia\Inertia;

class VoucherController extends Controller
{
    /**
     * Display a listing of vouchers
     */
    public function index()
    {
        $vouchers = Voucher::orderBy('created_at', 'desc')->get();
        $masks = $this->getMasksForSelect();

        return Inertia::render('admin/vouchers/pages/VoucherListPage', [
            'vouchers' => $vouchers,
            'masks' => $masks,
        ]);
    }

    /**
     * Show the form for creating a new voucher
     */
    public function create()
    {
        $masks = $this->getMasksForSelect();

        return Inertia::render('admin/vouchers/pages/VoucherCreatePage', [
            'masks' => $masks,
        ]);
    }

    /**
     * Store a newly created voucher
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'item_id' => 'required|integer',
            'count' => 'required|integer|min:1',
            'proctype' => 'required|integer',
            'octet' => 'required|string',
            'duration' => 'nullable|string', // Allow empty, "none", or duration values
            'mask' => 'required|integer',
            'ip_restricted' => 'required|boolean',
            'usage_limit' => 'required|integer|min:1|max:1000',
            'eligible_register_date' => 'nullable|date',
        ]);

        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

        // Fetch item name
        $itemName = $this->getItemNameById($request->item_id);

        // Calculate expire date from duration (null if no duration or "none")
        $expireDate = null;
        $duration = $request->duration;
        if (! empty($duration) && $duration !== 'none' && is_numeric($duration)) {
            $expireDate = now()->addSeconds((int) $duration);
        }

        $voucher = new Voucher;
        $voucher->code = $this->generateVoucherCode();
        $voucher->item_id = $request->item_id;
        $voucher->item_name = $itemName;
        $voucher->count = $request->count;
        $voucher->proctype = $request->proctype;
        $voucher->octet = $request->octet;
        $voucher->expire_date = $expireDate;
        $voucher->mask = $request->mask;
        $voucher->is_redeemed_by_ip = $request->ip_restricted;
        $voucher->usage_limit = $request->usage_limit;
        $voucher->usage_count = 0; // Start with 0 usage
        $voucher->eligible_register_date = empty($request->eligible_register_date) ? null : $request->eligible_register_date;
        $voucher->save();

        return to_route('admin.vouchers.index')
            ->with('success', 'Voucher created successfully!');
    }

    /**
     * Update the specified voucher
     */
    public function update(Request $request, $id)
    {
        $validator = Validator::make($request->all(), [
            'item_id' => 'required|integer',
            'count' => 'required|integer|min:1',
            'proctype' => 'required|integer',
            'octet' => 'required|string',
            'expire_date' => 'nullable|date',
            'mask' => 'required|integer',
            'eligible_register_date' => 'nullable|date',
        ]);

        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

        $voucher = Voucher::findOrFail($id);

        // Don't allow editing used vouchers
        if ($voucher->is_used) {
            return back()->withErrors(['error' => 'Cannot edit a used voucher']);
        }

        // Fetch item name
        $itemName = $this->getItemNameById($request->item_id);

        $voucher->item_id = $request->item_id;
        $voucher->item_name = $itemName;
        $voucher->count = $request->count;
        $voucher->proctype = $request->proctype;
        $voucher->octet = $request->octet;
        $voucher->expire_date = $request->expire_date;
        $voucher->mask = $request->mask;
        $voucher->eligible_register_date = empty($request->eligible_register_date) ? null : $request->eligible_register_date;
        $voucher->save();

        return to_route('admin.vouchers.index')
            ->with('success', 'Voucher updated successfully!');
    }

    /**
     * Remove the specified voucher
     */
    public function destroy($id)
    {
        $voucher = Voucher::findOrFail($id);

        // Don't allow deleting used vouchers
        if ($voucher->is_used) {
            return back()->withErrors(['error' => 'Cannot delete a used voucher']);
        }

        $voucher->delete();

        return to_route('admin.vouchers.index')
            ->with('success', 'Voucher deleted successfully!');
    }

    /**
     * Clone an existing voucher
     */
    public function clone($id)
    {
        $originalVoucher = Voucher::findOrFail($id);

        $newVoucher = new Voucher;
        $newVoucher->code = $this->generateVoucherCode();
        $newVoucher->item_id = $originalVoucher->item_id;
        $newVoucher->item_name = $originalVoucher->item_name;
        $newVoucher->count = $originalVoucher->count;
        $newVoucher->proctype = $originalVoucher->proctype;
        $newVoucher->octet = $originalVoucher->octet;
        $newVoucher->expire_date = $originalVoucher->expire_date;
        $newVoucher->mask = $originalVoucher->mask;
        $newVoucher->is_redeemed_by_ip = $originalVoucher->is_redeemed_by_ip;
        $newVoucher->usage_limit = $originalVoucher->usage_limit;
        $newVoucher->eligible_register_date = $originalVoucher->eligible_register_date;
        $newVoucher->save();

        return to_route('admin.vouchers.index')
            ->with('success', 'Voucher cloned successfully!');
    }

    /**
     * Get item name by ID from RAE_Exported_Table.tab
     */
    public function getItems(Request $request)
    {
        $filePath = public_path('img/RAE_Exported_Table.tab');

        if (! file_exists($filePath)) {
            return response()->json(['error' => 'Item file not found'], 404);
        }

        $itemId = $request->query('item_id');

        // If item_id is provided, return only that item
        if ($itemId !== null) {
            $file = fopen($filePath, 'r');

            while (($line = fgets($file)) !== false) {
                $parts = explode("\t", trim($line));

                if (count($parts) >= 3) {
                    $id = trim($parts[0]);
                    $name = trim($parts[2]);

                    if ($id == $itemId && ! empty($name)) {
                        fclose($file);

                        return response()->json([
                            'id' => (int) $id,
                            'name' => $name,
                        ]);
                    }
                }
            }

            fclose($file);

            return response()->json(['error' => 'Item not found'], 404);
        }

        return response()->json(['items' => []]);
    }

    /**
     * Generate a unique 16-digit voucher code in format xxxx-xxxx-xxxx-xxxx
     */
    private function generateVoucherCode()
    {
        do {
            $code = strtoupper(
                Str::random(4).'-'.
                Str::random(4).'-'.
                Str::random(4).'-'.
                Str::random(4)
            );
        } while (Voucher::where('code', $code)->exists());

        return $code;
    }

    /**
     * Get item name by ID
     */
    private function getItemNameById($itemId)
    {
        $filePath = public_path('img/RAE_Exported_Table.tab');

        if (! file_exists($filePath)) {
            return null;
        }

        $file = fopen($filePath, 'r');

        while (($line = fgets($file)) !== false) {
            $parts = explode("\t", trim($line));

            if (count($parts) >= 3) {
                $id = trim($parts[0]);
                $name = trim($parts[2]);

                if ($id == $itemId && ! empty($name)) {
                    fclose($file);

                    return $name;
                }
            }
        }

        fclose($file);

        return null;
    }

    /**
     * Get masks formatted for select dropdown
     */
    private function getMasksForSelect()
    {
        $masks = config('masks');
        $formatted = [];

        foreach ($masks as $key => $value) {
            if (is_array($value)) {
                // Group
                $formatted[] = [
                    'label' => $key,
                    'options' => array_map(function ($k, $v) {
                        return ['value' => $k, 'label' => $v];
                    }, array_keys($value), $value),
                ];
            } else {
                // Single option
                $formatted[] = [
                    'value' => $key,
                    'label' => $value,
                ];
            }
        }

        return $formatted;
    }
}
