<?php

namespace App\Http\Controllers;

use App\Models\NumberingFormat;
use App\Models\Store;
use Illuminate\Http\Request;

class NumberingFormatsController extends Controller
{
    public $logged_user_id;

    public function __construct()
    {
        $this->middleware(function ($request, $next) {
            $this->logged_user_id = auth()->id();
            return $next($request);
        });
    }

    public function index(Request $request)
    {
        if ($request->ajax()) {
            $query = NumberingFormat::select('m_numbering_formats.*')
                ->with('store')
                ->where('delete_flag', false);

            // Filter by store if specified
            if ($request->has('store_id') && $request->store_id) {
                $query->forStore($request->store_id);
            }

            // Filter by document type if specified
            if ($request->has('document_type') && $request->document_type) {
                $query->forDocumentType($request->document_type);
            }

            // Filter by SPB type if specified
            if ($request->has('spb_type') && $request->spb_type) {
                $query->forSpbType($request->spb_type);
            }

            // Filter by item type if specified
            if ($request->has('item_type') && $request->item_type) {
                $query->forItemType($request->item_type);
            }

            // Searching
            if ($request->has('search') && $request->search['value'] != '') {
                $search = $request->search['value'];
                $query->where(function ($q) use ($search) {
                    $q->where('document_type', 'ilike', "%{$search}%")
                        ->orWhere('spb_type', 'ilike', "%{$search}%")
                        ->orWhere('item_type', 'ilike', "%{$search}%")
                        ->orWhere('format_pattern', 'ilike', "%{$search}%")
                        ->orWhere('prefix', 'ilike', "%{$search}%")
                        ->orWhereHas('store', function($sq) use ($search) {
                            $sq->where('name', 'ilike', "%{$search}%")
                              ->orWhere('code', 'ilike', "%{$search}%");
                        });
                });
            }

            $total = $query->count();

            // Sorting
            $columns = ['id', 'store_id', 'document_type', 'spb_type', 'item_type', 'format_pattern', 'current_number', 'reset_period', 'is_active'];
            $orderColumn = $columns[$request->order[0]['column']] ?? 'document_type';
            $orderDir = $request->order[0]['dir'] ?? 'asc';

            $query->orderBy($orderColumn, $orderDir);

            // Pagination
            $start = $request->start;
            $length = $request->length;
            $data = $query->skip($start)->take($length)->get();

            // Format data
            $result = [];
            $no = $start + 1;
            foreach ($data as $row) {
                $statusBadge = $row->is_active ? '<span class="badge badge-success">Active</span>' : '<span class="badge badge-secondary">Inactive</span>';
                $docTypeBadge = '<span class="badge ' . $row->document_type_badge . '">' . $row->document_type . '</span>';
                
                // SPB Type badge
                $spbTypeBadge = '<span class="badge badge-secondary">' . $row->spb_type . '</span>';
                
                // Item Type badge
                $itemTypeBadge = '<span class="badge badge-info">' . $row->item_type . '</span>';
                
                $preview = $row->getNextNumberPreview();
                $resetInfo = $row->reset_period;
                if ($row->needsReset()) {
                    $resetInfo .= ' <span class="badge badge-secondary">Needs Reset</span>';
                }
                
                $result[] = [
                    $no++,
                    $row->store ? $row->store->name : 'All Stores',
                    $docTypeBadge,
                    $spbTypeBadge,
                    $itemTypeBadge,
                    '<code>' . $row->format_pattern . '</code>',
                    '<strong>' . $preview . '</strong>',
                    $row->current_number,
                    $resetInfo,
                    $statusBadge,
                    '<a href="' . route('numbering_formats.show', $row->id) . '" class="btn btn-sm btn-info">View</a>'
                ];
            }

            return response()->json([
                "draw" => intval($request->draw),
                "recordsTotal" => $total,
                "recordsFiltered" => $total,
                "data" => $result,
            ]);
        }

        // Get stores and document types for filters
        $stores = Store::active()->orderBy('name')->get();
        $documentTypes = NumberingFormat::getDocumentTypes();
        $spbTypes = NumberingFormat::getSpbTypes();
        $itemTypes = NumberingFormat::getItemTypes();

        return view('m-numbering-formats.index', [
            'variables' => $this->variables([
                'stores' => $stores,
                'document_types' => $documentTypes,
                'spb_types' => $spbTypes,
                'item_types' => $itemTypes
            ])
        ]);
    }

    public function create()
    {
        $variables['judul'] = 'Add Numbering Format';
        $variables['stores'] = Store::active()->orderBy('name')->get();
        $variables['document_types'] = NumberingFormat::getDocumentTypes();
        $variables['spb_types'] = NumberingFormat::getSpbTypes();
        $variables['item_types'] = NumberingFormat::getItemTypes();
        $variables['reset_periods'] = NumberingFormat::getResetPeriods();
        $variables['pattern_examples'] = NumberingFormat::getPatternExamples();
        $variables['placeholders'] = NumberingFormat::getPlaceholders();
        
        return view('m-numbering-formats.form', [
            'data' => json_decode(json_encode(array('id' => 0))),
            'variables' => $this->variables($variables)
        ]);
    }

    public function edit(NumberingFormat $numberingFormat)
    {
        $variables['judul'] = 'Edit Numbering Format';
        $variables['stores'] = Store::active()->orderBy('name')->get();
        $variables['document_types'] = NumberingFormat::getDocumentTypes();
        $variables['spb_types'] = NumberingFormat::getSpbTypes();
        $variables['item_types'] = NumberingFormat::getItemTypes();
        $variables['reset_periods'] = NumberingFormat::getResetPeriods();
        $variables['pattern_examples'] = NumberingFormat::getPatternExamples();
        $variables['placeholders'] = NumberingFormat::getPlaceholders();
        
        return view('m-numbering-formats.form', [
            'data' => $numberingFormat,
            'variables' => $this->variables($variables)
        ]);
    }

    public function store(Request $request, $prm_id = null)
    {
        $numberingFormat = null;
        if ($prm_id)
            $numberingFormat = NumberingFormat::findOrFail($prm_id);

        $rules = [
            'store_id' => 'required|exists:m_stores,id',
            'document_type' => 'required|in:' . implode(',', array_keys(NumberingFormat::getDocumentTypes())),
            'spb_type' => 'required|in:' . implode(',', array_keys(NumberingFormat::getSpbTypes())),
            'item_type' => 'required|in:' . implode(',', array_keys(NumberingFormat::getItemTypes())),
            'format_pattern' => 'required|string|max:255',
            'prefix' => 'nullable|string|max:20',
            'suffix' => 'nullable|string|max:20',
            'separator' => 'nullable|string|max:5',
            'number_length' => 'required|integer|min:1|max:10',
            'reset_period' => 'required|in:' . implode(',', array_keys(NumberingFormat::getResetPeriods())),
            'current_number' => 'nullable|integer|min:0',
            'is_active' => 'boolean'
        ];

        // Check for duplicate store + document_type + spb_type + item_type combination
        $uniqueRule = 'unique:m_numbering_formats,store_id';
        if ($numberingFormat) {
            $uniqueRule .= ',' . $numberingFormat->id;
        }
        $uniqueRule .= ',id,document_type,' . $request->document_type;
        $uniqueRule .= ',spb_type,' . $request->spb_type;
        $uniqueRule .= ',item_type,' . $request->item_type;
        $uniqueRule .= ',delete_flag,false';
        
        $rules['store_id'] .= '|' . $uniqueRule;

        $messages = [
            'store_id.unique' => 'Numbering format for this store, document type, SPB type, and item type combination already exists.',
            'spb_type.required' => 'SPB Type is required.',
            'item_type.required' => 'Item Type is required.'
        ];
        
        $saveData = $request->validate($rules, $messages);

        // Set default values
        $saveData['current_number'] = $saveData['current_number'] ?? 0;
        $saveData['is_active'] = $request->has('is_active');

        try {
            if ($numberingFormat) {
                $numberingFormat->update(array_merge($saveData, [
                    'updated_by' => $this->logged_user_id,
                ]));
            } else {
                NumberingFormat::create(array_merge($saveData, [
                    'last_reset_date' => now()->format('Y-m-d'),
                    'delete_flag' => false,
                    'created_by' => $this->logged_user_id,
                    'updated_by' => $this->logged_user_id,
                ]));
            }

            $notif = $numberingFormat ? 'Updated successfully.' : 'Successfully created.';
            return response()->json(['success', $notif]);
            
        } catch (\Exception $e) {
            $notif = $this->getErrorCatch($e->getMessage());
            return response()->json(['warning', $notif]);
        }
    }

    public function show(NumberingFormat $numberingFormat)
    {
        $numberingFormat->load(['store', 'creator', 'modificator']);
        $variables['judul'] = 'View Numbering Format: ' . $numberingFormat->document_type;
        return view('m-numbering-formats.show', [
            'data' => $numberingFormat,
            'variables' => $this->variables($variables)
        ]);
    }

    public function destroy(NumberingFormat $numberingFormat)
    {
        $numberingFormat->update([
            'delete_flag' => true,
            'updated_by' => $this->logged_user_id
        ]);

        return redirect()->route('numbering_formats.index')
            ->with('success', 'Successfully deleted');
    }

    // API method to preview format
    public function previewFormat(Request $request)
    {
        $pattern = $request->get('pattern');
        $storeId = $request->get('store_id');
        $documentType = $request->get('document_type');
        $prefix = $request->get('prefix', '');
        $suffix = $request->get('suffix', '');
        $separator = $request->get('separator', '-');
        $numberLength = $request->get('number_length', 4);
        $sampleNumber = $request->get('sample_number', 1);

        if (!$pattern || !$storeId || !$documentType) {
            return response()->json(['error' => 'Missing required parameters'], 400);
        }

        // Create temporary format object for preview
        $tempFormat = new NumberingFormat([
            'store_id' => $storeId,
            'document_type' => $documentType,
            'format_pattern' => $pattern,
            'prefix' => $prefix,
            'suffix' => $suffix,
            'separator' => $separator,
            'number_length' => $numberLength
        ]);

        // Load store relationship
        $tempFormat->store = Store::find($storeId);

        $preview = $tempFormat->previewFormat($sampleNumber);

        return response()->json([
            'preview' => $preview,
            'pattern' => $pattern,
            'sample_number' => $sampleNumber
        ]);
    }

    // API method to generate next number
    public function generateNumber(Request $request)
    {
        $storeId = $request->get('store_id');
        $documentType = $request->get('document_type');
        $spbType = $request->get('spb_type', 'All');
        $itemType = $request->get('item_type', 'All');

        if (!$storeId || !$documentType) {
            return response()->json(['error' => 'store_id and document_type required'], 400);
        }

        try {
            $number = NumberingFormat::generateNumber($storeId, $documentType, $spbType, $itemType);
            
            return response()->json([
                'number' => $number,
                'store_id' => $storeId,
                'document_type' => $documentType,
                'spb_type' => $spbType,
                'item_type' => $itemType
            ]);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    // Method to reset counter
    public function resetCounter(Request $request, NumberingFormat $numberingFormat)
    {
        try {
            $numberingFormat->update([
                'current_number' => 0,
                'last_reset_date' => now()->format('Y-m-d'),
                'updated_by' => $this->logged_user_id
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Counter reset successfully',
                'new_preview' => $numberingFormat->getNextNumberPreview()
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error resetting counter: ' . $e->getMessage()
            ], 500);
        }
    }

    private function variables($variables = [])
    {
        $defaultVariables = [
            'header_routes' => '
                <li class="breadcrumb-item">Master Data</li>
                <li class="breadcrumb-item active">Numbering Formats</li>
            ',
            'judul' => 'Numbering Formats'
        ];

        return array_merge($defaultVariables, $variables);
    }

    private function getErrorCatch($e)
    {
        if (strpos($e, '#error#') !== false) {
            $e = explode('#error#', $e);
            $e = $e[1];
        }

        return $e;
    }
}