<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Customer;
use App\Models\CustomerNote;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;

class CustomerController extends Controller
{
    /**
     * Display a listing of customers
     */
    public function index(Request $request): JsonResponse
    {
        $query = Customer::query();

        // Filter by customer type
        if ($request->has('customer_type')) {
            $query->where('customer_type', $request->customer_type);
        }

        // Filter by active status
        if ($request->has('is_active')) {
            $query->where('is_active', $request->is_active);
        }

        // Search by name, phone, or email
        if ($request->has('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('phone', 'like', "%{$search}%")
                    ->orWhere('email', 'like', "%{$search}%");
            });
        }

        $customers = $query->orderBy('created_at', 'desc')->paginate(15);

        return response()->json([
            'success' => true,
            'data' => $customers,
        ]);
    }

    /**
     * Store a newly created customer
     */
    public function store(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:customers,email',
            'phone' => 'required|string|max:20|unique:customers,phone',
            'secondary_phone' => 'nullable|string|max:20',
            'address' => 'nullable|string',
            'city' => 'nullable|string|max:100',
            'country' => 'nullable|string|max:100',
            'cnic' => 'nullable|string|max:20',
            'date_of_birth' => 'nullable|date',
            'customer_type' => 'required|in:retail,wholesale,corporate',
            'credit_limit' => 'nullable|numeric|min:0',
            'notes' => 'nullable|array',
            'notes.*' => 'nullable|string',
            'is_active' => 'sometimes|boolean',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors()
            ], 422);
        }

        DB::beginTransaction();

        try {
            $validatedData = $validator->validated();
            $notesArray = $validatedData['notes'] ?? [];
            unset($validatedData['notes']);

            // Create customer
            $customer = Customer::create($validatedData);

            // Create notes if provided
            if (!empty($notesArray)) {
                foreach ($notesArray as $noteText) {
                    if (!empty(trim($noteText))) {
                        CustomerNote::create([
                            'customer_id' => $customer->id,
                            'note' => $noteText,
                            'created_by' => auth()->id(),
                        ]);
                    }
                }
            }

            DB::commit();

            // Load notes relationship
            $customer->load('customerNotes');

            return response()->json([
                'success' => true,
                'message' => 'Customer created successfully',
                'data' => $customer,
            ], 201);
        } catch (\Exception $e) {
            DB::rollBack();

            return response()->json([
                'success' => false,
                'message' => 'Failed to create customer: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Display the specified customer
     */
    public function show($id): JsonResponse
    {
        $customer = Customer::with('customerNotes.createdBy')->find($id);

        if (!$customer) {
            return response()->json([
                'success' => false,
                'message' => 'Customer not found'
            ], 404);
        }

        // Load relationships for better performance
        $customer->loadCount('sales');

        // Add computed attributes
        $customerData = $customer->toArray();
        $customerData['total_purchases'] = $customer->total_purchases;
        $customerData['total_due'] = $customer->total_due;
        $customerData['total_paid'] = $customer->total_paid;

        return response()->json([
            'success' => true,
            'data' => $customerData,
        ]);
    }

    /**
     * Update the specified customer
     */
    public function update(Request $request, $id): JsonResponse
    {
        $customer = Customer::find($id);

        if (!$customer) {
            return response()->json([
                'success' => false,
                'message' => 'Customer not found'
            ], 404);
        }

        $validator = Validator::make($request->all(), [
            'name' => 'sometimes|required|string|max:255',
            'email' => ['sometimes', 'required', 'email', Rule::unique('customers')->ignore($customer->id)],
            'phone' => ['sometimes', 'required', 'string', 'max:20', Rule::unique('customers')->ignore($customer->id)],
            'secondary_phone' => 'nullable|string|max:20',
            'address' => 'nullable|string',
            'city' => 'nullable|string|max:100',
            'country' => 'nullable|string|max:100',
            'cnic' => 'nullable|string|max:20',
            'date_of_birth' => 'nullable|date',
            'customer_type' => 'sometimes|required|in:retail,wholesale,corporate',
            'credit_limit' => 'nullable|numeric|min:0',
            'notes' => 'nullable|array',
            'notes.*' => 'nullable|string',
            'is_active' => 'sometimes|boolean',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors()
            ], 422);
        }

        DB::beginTransaction();

        try {
            $validatedData = $validator->validated();
            $notesArray = $validatedData['notes'] ?? null;
            unset($validatedData['notes']);

            // Update customer
            $customer->update($validatedData);

            // Update notes if provided
            if ($notesArray !== null) {
                // Delete existing notes
                $customer->customerNotes()->delete();

                // Create new notes
                foreach ($notesArray as $noteText) {
                    if (!empty(trim($noteText))) {
                        CustomerNote::create([
                            'customer_id' => $customer->id,
                            'note' => $noteText,
                            'created_by' => auth()->id(),
                        ]);
                    }
                }
            }

            DB::commit();

            // Reload customer with notes
            $customer = $customer->fresh(['customerNotes']);

            return response()->json([
                'success' => true,
                'message' => 'Customer updated successfully',
                'data' => $customer,
            ]);
        } catch (\Exception $e) {
            DB::rollBack();

            return response()->json([
                'success' => false,
                'message' => 'Failed to update customer: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Remove the specified customer
     */
    public function destroy($id): JsonResponse
    {
        $customer = Customer::find($id);

        if (!$customer) {
            return response()->json([
                'success' => false,
                'message' => 'Customer not found'
            ], 404);
        }

        // Check if customer has sales
        if ($customer->sales()->exists()) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot delete customer with existing sales records'
            ], 422);
        }

        // Notes will be deleted automatically due to cascade
        $customer->delete();

        return response()->json([
            'success' => true,
            'message' => 'Customer deleted successfully',
        ]);
    }

    /**
     * Toggle customer active status
     */
    public function toggleStatus($id): JsonResponse
    {
        $customer = Customer::find($id);

        if (!$customer) {
            return response()->json([
                'success' => false,
                'message' => 'Customer not found'
            ], 404);
        }

        $customer->is_active = !$customer->is_active;
        $customer->save();

        return response()->json([
            'success' => true,
            'message' => 'Customer status updated successfully',
            'data' => $customer,
        ]);
    }

    /**
     * Get customer purchase history
     */
    public function purchaseHistory($id): JsonResponse
    {
        $customer = Customer::with('customerNotes')->find($id);

        if (!$customer) {
            return response()->json([
                'success' => false,
                'message' => 'Customer not found'
            ], 404);
        }

        $sales = $customer->sales()
            ->with(['saleItems.inventory', 'soldBy'])
            ->orderBy('sale_date', 'desc')
            ->paginate(15);

        return response()->json([
            'success' => true,
            'data' => [
                'customer' => $customer,
                'sales' => $sales,
                'total_purchases' => $customer->total_purchases,
                'total_due' => $customer->total_due,
            ],
        ]);
    }

    /**
     * Get customers with due payments
     */
    public function customersWithDue(): JsonResponse
    {
        $customers = Customer::whereHas('sales', function ($query) {
            $query->whereIn('payment_status', ['pending', 'partial']);
        })
            ->withCount('sales')
            ->with(['sales' => function ($query) {
                $query->whereIn('payment_status', ['pending', 'partial'])
                    ->select('id', 'customer_id', 'invoice_number', 'total_amount', 'due_amount', 'sale_date');
            }])
            ->orderBy('created_at', 'desc')
            ->paginate(15);

        return response()->json([
            'success' => true,
            'data' => $customers,
        ]);
    }

    /**
     * Get active customers
     */
    public function activeCustomers(): JsonResponse
    {
        $customers = Customer::where('is_active', true)
            ->orderBy('name', 'asc')
            ->paginate(15);

        return response()->json([
            'success' => true,
            'data' => $customers,
        ]);
    }

    /**
     * Get customers by type
     */
    public function getByType($type): JsonResponse
    {
        if (!in_array($type, ['retail', 'wholesale', 'corporate'])) {
            return response()->json([
                'success' => false,
                'message' => 'Invalid customer type'
            ], 422);
        }

        $customers = Customer::where('customer_type', $type)
            ->orderBy('name', 'asc')
            ->paginate(15);

        return response()->json([
            'success' => true,
            'data' => $customers,
        ]);
    }


    /**
     * Get customer statistics
     */
    public function getStats(Request $request): JsonResponse
    {
        $query = Customer::query();

        // Apply same filters as index method for consistency
        // if ($request->has('customer_type')) {
        //     $query->where('customer_type', $request->customer_type);
        // }

        if ($request->has('is_active')) {
            $query->where('is_active', $request->is_active);
        }

        if ($request->has('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('phone', 'like', "%{$search}%")
                    ->orWhere('email', 'like', "%{$search}%");
            });
        }

        // Apply date filters if provided
        if ($request->has('date_from')) {
            $query->whereDate('created_at', '>=', $request->date_from);
        }

        if ($request->has('date_to')) {
            $query->whereDate('created_at', '<=', $request->date_to);
        }

        // Apply contact filters
        if ($request->has('has_email') && $request->has_email) {
            $query->whereNotNull('email')->where('email', '!=', '');
        }

        if ($request->has('has_phone') && $request->has_phone) {
            $query->whereNotNull('phone')->where('phone', '!=', '');
        }

        $stats = [
            'total' => (clone $query)->count(),
            'active' => (clone $query)->where('is_active', true)->count(),
            'inactive' => (clone $query)->where('is_active', false)->count(),
            'withoutEmail' => (clone $query)->where(function ($q) {
                $q->whereNull('email')->orWhere('email', '');
            })->count(),
            'withoutPhone' => (clone $query)->where(function ($q) {
                $q->whereNull('phone')->orWhere('phone', '');
            })->count(),
            'retail' => (clone $query)->where('customer_type', 'retail')->count(),
            'wholesale' => (clone $query)->where('customer_type', 'wholesale')->count(),
            'corporate' => (clone $query)->where('customer_type', 'corporate')->count(),
        ];

        return response()->json([
            'success' => true,
            'data' => $stats,
        ]);
    }
}
