<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreSaleRequest;
use App\Models\Customer;
use App\Models\Line;
use App\Models\Plan;
use App\Models\Sale;
use App\Models\TelecomCompany;
use App\Services\LineSaleService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class SaleController extends Controller
{
    public function __construct(protected LineSaleService $service)
    {
        $this->middleware('permission:sales.view')->only(['index', 'show']);
        $this->middleware('permission:sales.create')->only(['create', 'store', 'lookupCustomers', 'lookupLines', 'lookupPlans']);
    }

    public function index(Request $request)
    {
        $sales = Sale::query()
            ->with(['customer', 'line', 'plan', 'user'])
            ->when($request->q, fn ($q, $v) => $q->where('sale_number', 'like', "%{$v}%")
                ->orWhereHas('customer', fn ($c) => $c->where('name', 'like', "%{$v}%")->orWhere('phone', 'like', "%{$v}%"))
                ->orWhereHas('line', fn ($l) => $l->where('phone_number', 'like', "%{$v}%")))
            ->latest('sale_date')
            ->latest('id')
            ->paginate(per_page())
            ->withQueryString();

        return view('sales.index', compact('sales'));
    }

    public function create()
    {
        $companies = TelecomCompany::query()
            ->where('status', 'active')
            ->withCount([
                'lines as available_lines_count' => fn ($q) => $q->where('status', 'available'),
                'plans as active_plans_count' => fn ($q) => $q->where('status', 'active'),
            ])
            ->orderBy('name')
            ->get();

        return view('sales.create', [
            'canOverridePrice' => auth()->user()?->can('sales.override_price') ?? false,
            'companies' => $companies,
        ]);
    }

    public function store(StoreSaleRequest $request)
    {
        $data = $request->validated();
        $data['override_price'] = $request->boolean('override_price') && $request->user()->can('sales.override_price');
        $data['sale_date'] = $data['sale_date'] ?? now()->toDateString();
        $data['activation_date'] = $data['activation_date'] ?? $data['sale_date'];

        $sale = $this->service->sell($data, $request->user());

        return redirect()->route('sales.show', $sale)->with('success', __('messages.sale_completed'));
    }

    public function show(Sale $sale)
    {
        $sale->load(['customer', 'line', 'plan', 'invoice.items', 'items', 'user', 'overriddenBy']);

        return view('sales.show', compact('sale'));
    }

    public function lookupCustomers(Request $request): JsonResponse
    {
        $term = trim((string) $request->get('q', ''));
        $customers = Customer::query()
            ->with(['mainAccount', 'subAccount'])
            ->when($term !== '', fn ($q) => $q->search($term))
            ->orderBy('name')
            ->limit(15)
            ->get()
            ->map(fn (Customer $c) => [
                'id' => $c->id,
                'name' => $c->name,
                'phone' => $c->phone,
                'national_id' => $c->national_id,
                'type' => $c->customer_type->value,
                'type_label' => $c->customer_type->label(),
                'main_account_id' => $c->main_account_id,
                'sub_account_id' => $c->sub_account_id,
                'main_account' => $c->mainAccount?->name,
                'sub_account' => $c->subAccount?->name,
            ]);

        return response()->json($customers);
    }

    public function lookupLines(Request $request): JsonResponse
    {
        $term = trim((string) $request->get('q', ''));
        $companyId = $request->integer('telecom_company_id');

        $lines = Line::query()
            ->with('telecomCompany')
            ->where('status', 'available')
            ->when($companyId, fn ($q) => $q->where('telecom_company_id', $companyId))
            ->when($term !== '', fn ($q) => $q->where(function ($inner) use ($term) {
                $inner->where('phone_number', 'like', "%{$term}%")
                    ->orWhere('iccid', 'like', "%{$term}%");
            }))
            ->orderBy('phone_number')
            ->limit($companyId ? 300 : 20)
            ->get()
            ->map(fn (Line $line) => [
                'id' => $line->id,
                'phone_number' => $line->phone_number,
                'company' => $line->telecomCompany?->name,
                'telecom_company_id' => $line->telecom_company_id,
                'sale_price' => (string) ($line->sale_price ?? '0.00'),
                'sim_type' => $line->sim_type->value,
                'sim_type_label' => $line->sim_type->label(),
                'status' => $line->status->value,
                'status_label' => $line->status->label(),
            ]);

        return response()->json($lines);
    }

    public function lookupPlans(Request $request): JsonResponse
    {
        $companyId = $request->integer('telecom_company_id');
        $plans = Plan::query()
            ->where('status', 'active')
            ->when($companyId, fn ($q) => $q->where('telecom_company_id', $companyId))
            ->orderBy('name')
            ->get()
            ->map(fn (Plan $plan) => [
                'id' => $plan->id,
                'name' => $plan->name,
                'price' => (string) $plan->price,
                'telecom_company_id' => $plan->telecom_company_id,
            ]);

        return response()->json($plans);
    }
}
