<?php

namespace Mtc\Modules\B2B\Services;

use Illuminate\Support\Facades\DB;
use Mtc\Modules\B2B\Enums\TradeCustomerStatus;
use Mtc\Modules\B2B\Events\TradeApplicationSubmittedEvent;
use Mtc\Modules\B2B\Models\TradeAddress;
use Mtc\Modules\B2B\Models\TradeCustomer;
use Mtc\Modules\Members\Classes\MemberManager;
use Mtc\Modules\Members\Models\Member;

class TradeRegistrationService
{
    private array $errors = [];

    public function __construct(private MemberManager $memberManager) {}

    public function register(array $data): ?TradeCustomer
    {
        $this->errors = [];

        // Validate required fields
        // billing_postcode = PAF search input, postcode = manual input; both normalised to postcode
        // by the controller, but we key the error to whichever field was in the original submission
        $postcodeField = array_key_exists('billing_postcode', $data) ? 'billing_postcode' : 'postcode';

        $required = [
            'company_name'      => 'company name',
            'billing_firstname' => 'first name',
            'billing_lastname'  => 'last name',
            'email'             => 'email address',
            'phone'             => 'phone number',
            'address_1'         => 'address line 1',
            'city'              => 'city',
            $postcodeField      => 'postcode',
        ];

        foreach ($required as $field => $label) {
            if (empty(trim($data[$field] ?? ''))) {
                $this->errors[$field] = "Please enter your {$label}";
            }
        }

        // Check email uniqueness against all members
        if (!empty($data['email']) && Member::withEmail($data['email'])->exists()) {
            $this->errors['email'] = 'There is already an account with this email address';
        }

        if (!empty($this->errors)) {
            return null;
        }

        return DB::transaction(function () use ($data) {
            // Create member via MemberManager
            $memberData = [
                'billing_firstname' => $data['billing_firstname'],
                'billing_lastname' => $data['billing_lastname'],
                'email' => $data['email'],
                'contact_no' => $data['phone'],
                'password' => $data['password'] ?? '',
                'password2' => $data['password2'] ?? '',
                'billing_address1' => $data['address_1'],
                'billing_address2' => $data['address_2'] ?? '',
                'billing_city' => $data['city'],
                'billing_state' => '',
                'billing_country' => 'GB',
                'billing_postcode' => $data['postcode'],
                'shipping_firstname' => $data['billing_firstname'],
                'shipping_lastname' => $data['billing_lastname'],
                'shipping_address1' => $data['address_1'],
                'shipping_address2' => $data['address_2'] ?? '',
                'shipping_city' => $data['city'],
                'shipping_state' => '',
                'shipping_country' => 'GB',
                'shipping_postcode' => $data['postcode'],
                'dob_year' => '1970',
                'dob_month' => '01',
                'dob_date' => '01',
                'gender' => '',
            ];

            $member = $this->memberManager->save($memberData, new Member());

            if (!$member) {
                $this->errors = $this->memberManager->getErrors();
                return null;
            }

            // Activate member immediately (they can log in but won't see trade pricing until approved)
            $member->is_activated = 1;
            $member->save();

            // Create trade customer record (status pending)
            $tradeCustomer = TradeCustomer::create([
                'member_id' => $member->id,
                'company_name' => $data['company_name'],
                'phone' => $data['phone'],
                'message' => $data['message'] ?? null,
                'status' => TradeCustomerStatus::Pending->value,
            ]);

            // Create trade address
            TradeAddress::create([
                'trade_customer_id' => $tradeCustomer->id,
                'address_1' => $data['address_1'],
                'address_2' => $data['address_2'] ?? null,
                'city' => $data['city'],
                'postcode' => $data['postcode'],
            ]);

            // Dispatch event for admin notification email
            TradeApplicationSubmittedEvent::dispatch($tradeCustomer->load(['member', 'address']));

            return $tradeCustomer;
        });
    }

    public function getErrors(): array
    {
        return $this->errors;
    }
}
