<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\StoreCategoryRequest;
use App\Http\Requests\Admin\UpdateCategoryRequest;
use App\Models\Category;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\View\View;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class CategoryController extends Controller
{
    public function index(Request $request): View
    {
        $query = Category::with('parent')
            ->withCount('products');

        if ($request->filled('search')) {
            $search = $request->get('search');
            $query->where('name', 'like', "%{$search}%");
        }

        if ($request->filled('status')) {
            $status = $request->get('status');
            if ($status === 'active') {
                $query->where('is_active', true);
            } elseif ($status === 'inactive') {
                $query->where('is_active', false);
            }
        }

        if ($request->filled('parent_id')) {
            if ($request->get('parent_id') === 'root') {
                $query->whereNull('parent_id');
            } else {
                $query->where('parent_id', $request->get('parent_id'));
            }
        }

        // Sort
        $sort = $request->get('sort', 'sort_order');
        $order = strtolower($request->get('order', 'asc')) === 'desc' ? 'desc' : 'asc';
        $allowedSorts = ['name', 'sort_order', 'created_at', 'products_count', 'parent'];
        if (!in_array($sort, $allowedSorts)) {
            $sort = 'sort_order';
        }
        if ($sort === 'products_count') {
            $query->orderBy('products_count', $order);
        } elseif ($sort === 'parent') {
            $query->orderByRaw('(SELECT name FROM categories p WHERE p.id = categories.parent_id) ' . ($order === 'desc' ? 'DESC' : 'ASC'));
        } else {
            $query->orderBy($sort, $order);
        }
        $query->orderBy('name', $sort === 'name' ? $order : 'asc');

        $categories = $query
            ->paginate(10)
            ->withQueryString();

        $parentCategories = Category::whereNull('parent_id')
            ->orderBy('name')
            ->get(['id', 'name']);

        return view('admin.categories.index', compact('categories', 'parentCategories', 'sort', 'order'));
    }

    public function create(): View
    {
        $parentCategories = Category::whereNull('parent_id')->orderBy('name')->get();

        return view('admin.categories.create', compact('parentCategories'));
    }

    public function store(StoreCategoryRequest $request): RedirectResponse
    {
        $data = $request->validated();
        $data['slug'] = Str::slug($data['name']);

        if ($request->hasFile('image')) {
            $data['image_path'] = $request->file('image')->store('categories', 'public');
        }

        Category::create($data);

        return redirect()->route('admin.categories.index')->with('success', 'Category created successfully!');
    }

    public function edit(Category $category): View
    {
        $parentCategories = Category::whereNull('parent_id')
            ->where('id', '!=', $category->id)
            ->orderBy('name')
            ->get();

        return view('admin.categories.edit', compact('category', 'parentCategories'));
    }

    public function update(UpdateCategoryRequest $request, Category $category): RedirectResponse
    {
        $data = $request->validated();

        if (isset($data['name']) && $data['name'] !== $category->name) {
            $data['slug'] = Str::slug($data['name']);
        }

        if ($request->hasFile('image')) {
            // Delete old image
            if ($category->image_path) {
                Storage::disk('public')->delete($category->image_path);
            }

            $data['image_path'] = $request->file('image')->store('categories', 'public');
        }

        $category->update($data);

        return redirect()->route('admin.categories.index')->with('success', 'Category updated successfully!');
    }

    public function destroy(Category $category): RedirectResponse
    {
        // Check if category has products
        $productCount = $category->products()->count();
        if ($productCount > 0) {
            return redirect()->route('admin.categories.index')
                ->with('error', "Cannot delete category. It is assigned to {$productCount} product(s). Please remove or reassign products first.");
        }

        // Check if category has child categories (subcategories)
        $childCount = $category->children()->count();
        if ($childCount > 0) {
            return redirect()->route('admin.categories.index')
                ->with('error', "Cannot delete category. It has {$childCount} subcategory(ies). Please delete or reassign subcategories first.");
        }

        // Delete image if exists
        if ($category->image_path) {
            Storage::disk('public')->delete($category->image_path);
        }

        $category->delete();

        return redirect()->route('admin.categories.index')->with('success', 'Category deleted successfully!');
    }

    public function downloadSample(): BinaryFileResponse
    {
        $csvData = [
            ['name', 'parent_category_name', 'sort_order', 'is_active'],
            ['Electronics', '', '1', '1'],
            ['Mobile Phones', 'Electronics', '1', '1'],
            ['Laptops', 'Electronics', '2', '1'],
            ['Clothing', '', '2', '1'],
            ['Men Clothing', 'Clothing', '1', '1'],
            ['Women Clothing', 'Clothing', '2', '1'],
        ];

        $filename = 'categories_import_sample.csv';
        $tempFile = tempnam(sys_get_temp_dir(), 'categories_sample_');
        
        $file = fopen($tempFile, 'w');
        
        // Add BOM for UTF-8 (helps with Excel)
        fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));
        
        foreach ($csvData as $row) {
            fputcsv($file, $row);
        }
        
        fclose($file);

        return response()->download($tempFile, $filename, [
            'Content-Type' => 'text/csv; charset=UTF-8',
        ])->deleteFileAfterSend(true);
    }

    public function import(Request $request): RedirectResponse
    {
        $request->validate([
            'import_file' => 'required|mimes:csv,txt|max:5120',
        ]);

        $file = $request->file('import_file');
        $path = $file->getRealPath();
        
        // Read CSV file with proper encoding and quote handling
        $data = [];
        if (($handle = fopen($path, 'r')) !== false) {
            while (($row = fgetcsv($handle, 1000, ',')) !== false) {
                $data[] = $row;
            }
            fclose($handle);
        }
        
        // Remove header row
        $header = array_shift($data);
        
        // Clean header (remove BOM if present)
        $header = array_map(function($value) {
            return trim(str_replace("\xEF\xBB\xBF", '', $value));
        }, $header);
        
        $imported = 0;
        $skipped = 0;
        $errors = [];

        DB::beginTransaction();

        try {
            foreach ($data as $index => $row) {
                $row = array_map('trim', $row);
                
                // Skip empty rows
                if (empty(array_filter($row))) {
                    continue;
                }

                // Validate row data
                if (count($row) < 1 || empty($row[0])) {
                    $skipped++;
                    $errors[] = "Row " . ($index + 2) . ": Name is required";
                    continue;
                }

                $categoryData = [
                    'name' => $row[0] ?? '',
                    'parent_category_name' => $row[1] ?? '',
                    'sort_order' => isset($row[2]) && is_numeric($row[2]) ? (int)$row[2] : 0,
                    'is_active' => isset($row[3]) ? (in_array(strtolower($row[3]), ['1', 'true', 'yes', 'active'])) : true,
                ];

                // Find parent category if specified (skip row if parent doesn't exist)
                $parentId = null;
                if (!empty($categoryData['parent_category_name'])) {
                    $parent = Category::where('name', $categoryData['parent_category_name'])->first();
                    if (!$parent) {
                        // Skip row if parent category doesn't exist (don't auto-create to prevent data quality issues)
                        $skipped++;
                        $errors[] = "Row " . ($index + 2) . ": Parent category '{$categoryData['parent_category_name']}' not found. Please create it first or correct the name.";
                        continue;
                    }
                    $parentId = $parent->id;
                }

                // Check if category already exists
                $existingCategory = Category::where('name', $categoryData['name'])
                    ->where('parent_id', $parentId)
                    ->first();

                if ($existingCategory) {
                    // Update existing category
                    $existingCategory->update([
                        'sort_order' => $categoryData['sort_order'],
                        'is_active' => $categoryData['is_active'],
                    ]);
                    $imported++;
                } else {
                    // Create new category
                    Category::create([
                        'name' => $categoryData['name'],
                        'slug' => Str::slug($categoryData['name']),
                        'parent_id' => $parentId,
                        'sort_order' => $categoryData['sort_order'],
                        'is_active' => $categoryData['is_active'],
                    ]);
                    $imported++;
                }
            }

            DB::commit();

            $message = "Successfully imported {$imported} category(ies)";
            if ($skipped > 0) {
                $message .= ". {$skipped} row(s) skipped.";
            }
            if (!empty($errors)) {
                $message .= " Errors: " . implode('; ', array_slice($errors, 0, 5));
                if (count($errors) > 5) {
                    $message .= ' and ' . (count($errors) - 5) . ' more.';
                }
            }

            return redirect()->route('admin.categories.index')
                ->with('success', $message);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Category import failed: ' . $e->getMessage());

            return redirect()->route('admin.categories.index')
                ->with('error', 'Import failed: ' . $e->getMessage());
        }
    }
}
