<?php

namespace Mtc\Modules\Members\Classes;

use App\Src\Encryption;
use Mtc\Modules\Members\Models\Member;
use Mtc\Modules\Members\Models\MembersAddress;

class MemberDuplicateCheck
{
    const THRESHOLD = 3;

    /**
     * Check if submitted data matches an existing member using combination matching.
     *
     * Scores each existing member against up to 5 identifying signals:
     *   email, phone, date of birth, postcode, full name (first + last).
     * If any candidate reaches THRESHOLD matches they are considered a duplicate.
     * Returns the most actionable field for the user to amend, or false.
     *
     * @param array $data  Keys: email, phone, dob, postcode, firstname, lastname, exclude_member_id
     * @return string|false  'email' | 'phone' | 'details' | false
     */
    public function hasDuplicates(array $data): string|false
    {
        // member_id => list of matched field names
        $matchedFields = [];
        \Log::info('Checking for duplicates', ['data' => $data]);

        if (!empty($data['email'])) {
            $hash = Encryption::makeHash($data['email']);
            Member::where('email_hash', $hash)
                ->pluck('id')
                ->each(function ($id) use (&$matchedFields) {
                    $matchedFields[$id][] = 'email';
                });
        }

        if (!empty($data['phone'])) {
            $hash = Encryption::makeHash($data['phone']);
            Member::where('contact_no_hash', $hash)
                ->pluck('id')
                ->each(function ($id) use (&$matchedFields) {
                    $matchedFields[$id][] = 'phone';
                });
        }

        if (!empty($data['dob'])) {
            $hash = Encryption::makeHash($data['dob']);
            Member::where('dob_hash', $hash)
                ->pluck('id')
                ->each(function ($id) use (&$matchedFields) {
                    $matchedFields[$id][] = 'dob';
                });
        }

        if (!empty($data['postcode'])) {
            $hash = Encryption::makeHash($data['postcode']);
            MembersAddress::where('type', MembersAddress::TYPE_BILLING)
                ->where('postcode_hash', $hash)
                ->pluck('member_id')
                ->each(function ($id) use (&$matchedFields) {
                    $matchedFields[$id][] = 'postcode';
                });
        }

        // Name counts as a single signal — both first and last must match
        if (!empty($data['firstname']) && !empty($data['lastname'])) {
            $firstHash = Encryption::makeHash($data['firstname']);
            $lastHash  = Encryption::makeHash($data['lastname']);
            MembersAddress::where('type', MembersAddress::TYPE_BILLING)
                ->where('firstname_hash', $firstHash)
                ->where('lastname_hash', $lastHash)
                ->pluck('member_id')
                ->each(function ($id) use (&$matchedFields) {
                    $matchedFields[$id][] = 'name';
                });
        }

        $excludeId = $data['exclude_member_id'] ?? null;

        foreach ($matchedFields as $memberId => $fields) {
            if ($excludeId && $memberId == $excludeId) {
                continue;
            }

            if (count($fields) >= self::THRESHOLD) {
                // Return the most actionable field for the user to amend
                if (in_array('email', $fields)) {
                    return 'email';
                }
                if (in_array('phone', $fields)) {
                    return 'phone';
                }
                return 'details';
            }
        }

        return false;
    }
}
