<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Api\V1\Concerns\RespondsWithApi;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class CustomerController extends Controller
{
    use RespondsWithApi;

    public function profile(Request $request)
    {
        return $this->ok($request->user());
    }

    public function addresses(Request $request)
    {
        return $this->ok(DB::table('customer_addresses')->where('user_id', $request->user()->id)->latest('is_default')->latest('id')->get());
    }

    public function storeAddress(Request $request)
    {
        $data = $request->validate($this->addressRules());
        $data['user_id'] = $request->user()->id;
        $data['created_at'] = now();
        $data['updated_at'] = now();

        if (! empty($data['is_default'])) {
            DB::table('customer_addresses')->where('user_id', $request->user()->id)->update(['is_default' => false]);
        }

        $id = DB::table('customer_addresses')->insertGetId($data);

        return $this->ok(DB::table('customer_addresses')->where('id', $id)->first(), 'Address added.', [], 201);
    }

    public function showAddress(Request $request, int $address)
    {
        $row = DB::table('customer_addresses')->where('id', $address)->where('user_id', $request->user()->id)->first();

        return $row ? $this->ok($row) : $this->fail('ADDRESS_NOT_FOUND', 'Address not found.', [], 404);
    }

    public function updateAddress(Request $request, int $address)
    {
        $row = DB::table('customer_addresses')->where('id', $address)->where('user_id', $request->user()->id)->first();

        if (! $row) {
            return $this->fail('ADDRESS_NOT_FOUND', 'Address not found.', [], 404);
        }

        $data = $request->validate($this->addressRules(false));
        $data['updated_at'] = now();

        if (! empty($data['is_default'])) {
            DB::table('customer_addresses')->where('user_id', $request->user()->id)->update(['is_default' => false]);
        }

        DB::table('customer_addresses')->where('id', $address)->update($data);

        return $this->ok(DB::table('customer_addresses')->where('id', $address)->first(), 'Address updated.');
    }

    public function deleteAddress(Request $request, int $address)
    {
        DB::table('customer_addresses')->where('id', $address)->where('user_id', $request->user()->id)->delete();

        return $this->ok([], 'Address deleted.');
    }

    public function setDefaultAddress(Request $request, int $address)
    {
        $exists = DB::table('customer_addresses')->where('id', $address)->where('user_id', $request->user()->id)->exists();

        if (! $exists) {
            return $this->fail('ADDRESS_NOT_FOUND', 'Address not found.', [], 404);
        }

        DB::table('customer_addresses')->where('user_id', $request->user()->id)->update(['is_default' => false]);
        DB::table('customer_addresses')->where('id', $address)->update(['is_default' => true, 'updated_at' => now()]);

        return $this->ok(DB::table('customer_addresses')->where('id', $address)->first(), 'Default address changed.');
    }

    private function addressRules(bool $required = true): array
    {
        $prefix = $required ? 'required' : 'sometimes';

        return [
            'city_id' => [$prefix, 'integer'],
            'locality_id' => ['nullable', 'integer'],
            'label' => ['nullable', 'string', 'max:80'],
            'address_line_1' => [$prefix, 'string', 'max:255'],
            'address_line_2' => ['nullable', 'string', 'max:255'],
            'landmark' => ['nullable', 'string', 'max:120'],
            'pincode' => ['nullable', 'string', 'max:12'],
            'lat' => ['nullable', 'numeric'],
            'lng' => ['nullable', 'numeric'],
            'society_name' => ['nullable', 'string', 'max:160'],
            'floor' => ['nullable', 'string', 'max:40'],
            'gate_instructions' => ['nullable', 'string', 'max:500'],
            'has_pets' => ['nullable', 'boolean'],
            'is_default' => ['nullable', 'boolean'],
        ];
    }
}
