<?php

namespace App\Http\Controllers;

use App\Enums\LineStatus;
use App\Http\Requests\StoreLineRequest;
use App\Models\Customer;
use App\Models\Line;
use App\Models\TelecomCompany;
use App\Services\ActivityService;
use App\Services\BillingService;
use App\Services\LineService;
use Illuminate\Http\Request;

class LineController extends Controller
{
    public function __construct(
        protected LineService $service,
        protected ActivityService $activity,
        protected BillingService $billing
    ) {
        $this->middleware('permission:lines.view')->only(['index', 'show']);
        $this->middleware('permission:lines.create')->only(['create', 'store']);
        $this->middleware('permission:lines.edit')->only(['edit', 'update']);
        $this->middleware('permission:lines.delete')->only(['destroy']);
        $this->middleware('permission:lines.transfer')->only(['transfer']);
        $this->middleware('permission:lines.cancel')->only(['returnLine', 'changeStatus']);
    }

    public function index(Request $request)
    {
        $lines = Line::query()
            ->with(['telecomCompany', 'customer', 'currentPlan', 'latestPayment'])
            ->search($request->get('q'))
            ->when($request->status, fn ($q, $v) => $q->where('status', $v))
            ->when($request->telecom_company_id, fn ($q, $v) => $q->where('telecom_company_id', $v))
            ->when($request->customer_id, fn ($q, $v) => $q->where('customer_id', $v))
            ->when($request->plan_id, fn ($q, $v) => $q->where('current_plan_id', $v))
            ->latest()
            ->paginate(per_page())
            ->withQueryString();

        return view('lines.index', [
            'lines' => $lines,
            'companies' => TelecomCompany::query()->orderBy('name')->get(),
            'statusFilter' => $request->get('status'),
        ]);
    }

    public function create()
    {
        return view('lines.create', $this->formData());
    }

    public function store(StoreLineRequest $request)
    {
        $line = $this->service->create($request->validated());

        return redirect()->route('lines.show', $line)->with('success', __('messages.created'));
    }

    public function show(Request $request, Line $line)
    {
        $tab = $request->get('tab', 'overview');
        $line->load(['telecomCompany', 'customer', 'currentPlan', 'mainAccount', 'subAccount']);

        $data = [
            'line' => $line,
            'tab' => $tab,
        ];

        if ($tab === 'billing') {
            $data['snapshot'] = $this->billing->snapshot($line);
        }
        if ($tab === 'invoices') {
            $data['invoices'] = $line->invoices()->with('customer')->latest('date')->paginate(per_page())->withQueryString();
        }
        if ($tab === 'payments') {
            $data['payments'] = $line->payments()->with('user')->latest('date')->paginate(per_page())->withQueryString();
        }
        if ($tab === 'history') {
            $data['ownership'] = $line->ownershipHistory()
                ->with(['user', 'previousCustomer', 'newCustomer'])
                ->paginate(per_page())
                ->withQueryString();
        }
        if ($tab === 'activity') {
            $data['activity'] = $this->activity->forLine($line);
        }
        if ($tab === 'customer') {
            $data['customers'] = Customer::query()->orderBy('name')->limit(200)->get(['id', 'name', 'phone']);
        }
        if ($tab === 'plan') {
            $data['assignments'] = $line->linePlans()->with('plan')->orderByDesc('id')->paginate(per_page())->withQueryString();
        }

        return view('lines.show', $data);
    }

    public function edit(Line $line)
    {
        return view('lines.edit', array_merge($this->formData(), compact('line')));
    }

    public function update(StoreLineRequest $request, Line $line)
    {
        $this->service->update($line, $request->validated(), $request->user());

        return redirect()->route('lines.show', $line)->with('success', __('messages.updated'));
    }

    public function destroy(Line $line)
    {
        if ($line->sales()->exists() || $line->invoices()->exists()) {
            $this->service->changeStatus($line, LineStatus::Cancelled, request()->user(), __('messages.cancelled'));
        } else {
            $line->delete();
        }

        return redirect()->route('lines.index')->with('success', __('messages.updated'));
    }

    public function transfer(Request $request, Line $line)
    {
        $data = $request->validate([
            'customer_id' => ['required', 'exists:customers,id'],
            'main_account_id' => ['nullable', 'exists:main_accounts,id'],
            'sub_account_id' => ['nullable', 'exists:sub_accounts,id'],
            'reason' => ['required', 'string', 'max:255'],
            'status' => ['nullable', 'string'],
        ]);
        $this->service->transfer($line, $data, $request->user());

        return back()->with('success', __('messages.line_transferred'));
    }

    public function returnLine(Request $request, Line $line)
    {
        $data = $request->validate([
            'reason' => ['required', 'string', 'max:255'],
            'target' => ['required', 'in:available,returned'],
        ]);
        $this->service->returnLine($line, $request->user(), $data['reason'], LineStatus::from($data['target']));

        return back()->with('success', __('messages.line_returned'));
    }

    protected function formData(): array
    {
        return [
            'companies' => TelecomCompany::query()->orderBy('name')->get(),
        ];
    }
}
