<?php

declare(strict_types=1);

namespace app\common\service;

use app\admin\model\split\Number;
use app\admin\model\split\Ticket;
use app\common\library\scrm\UnifiedScrmData;
use think\Db;

/**
 * 工单同步结果写入号码表
 *
 * 同步策略（全量镜像）：
 * - 爬虫返回的号码：写入 platform_status / inbound_count；status 由后续 applyNumberRules 裁决
 * - 爬虫未返回且 manual_manage=0：物理删除
 * - manual_manage=1：不删除，仅当仍在爬虫结果中时更新 platform_status
 */
class SplitTicketNumberSyncService
{
    /**
     * 将蜘蛛返回的号码列表同步到号码管理（全量镜像，以爬虫为准）
     */
    public function syncFromUnifiedData(Ticket $ticket, UnifiedScrmData $data): void
    {
        $adminId = (int) $ticket['admin_id'];
        $linkId = (int) $ticket['split_link_id'];
        $ticketName = (string) $ticket['ticket_name'];
        if ($linkId <= 0 || $ticketName === '') {
            return;
        }

        $randomShuffle = SplitNumberWeighService::isRandomShuffleEnabled($linkId);

        // 使用独立 number 字段存储，避免纯数字号码作为数组 key 被 PHP 自动转为 int
        $syncedNumbers = [];
        foreach ($data->numbers as $row) {
            $number = self::normalizeNumber($row['number'] ?? '');
            if ($number === '') {
                continue;
            }
            $syncedNumbers[] = [
                'number' => $number,
                'row'    => $row,
            ];
        }

        $existingList = Number::where('admin_id', $adminId)
            ->where('split_link_id', $linkId)
            ->where('ticket_name', $ticketName)
            ->select();

        $existingMap = [];
        foreach ($existingList as $item) {
            $existingMap[(string) $item['number']] = $item;
        }

        $syncedNumberSet = [];
        $pendingInserts = [];
        foreach ($syncedNumbers as $entry) {
            $number = $entry['number'];
            $row = $entry['row'];
            $syncedNumberSet[$number] = true;
            $platformStatus = ($row['status'] ?? '') === 'online' ? 'online' : 'offline';
            $newFollowers = (int) ($row['newFollowersToday'] ?? 0);

            if (isset($existingMap[$number])) {
                $this->updateExistingNumber($ticket, $existingMap[$number], $platformStatus, $newFollowers);
                continue;
            }

            $pendingInserts[] = [
                'number'          => $number,
                'platform_status' => $platformStatus,
                'new_followers'   => $newFollowers,
            ];
        }

        if ($pendingInserts !== []) {
            // 随机打乱：打乱待插入批次顺序，按随机顺序逐条 insert 以获得乱序自增 id
            if ($randomShuffle && count($pendingInserts) > 1) {
                shuffle($pendingInserts);
            }
            foreach ($pendingInserts as $item) {
                $this->insertNumber(
                    $ticket,
                    $item['number'],
                    $item['platform_status'],
                    $item['new_followers']
                );
            }
        }

        $deleteIds = [];
        foreach ($existingMap as $number => $item) {
            if (isset($syncedNumberSet[$number])) {
                continue;
            }
            if ((int) $item['manual_manage'] === 1) {
                continue;
            }
            $deleteIds[] = (int) $item['id'];
        }
        if ($deleteIds !== []) {
            Number::where('id', 'in', $deleteIds)->delete();
        }
    }

    /**
     * 工单手动开启等非同步场景：按业务规则对齐号码开关（平台 + 单号上限 + 下号比率）
     */
    public function applyStatusFromPlatformSnapshot(Ticket $ticket): void
    {
        (new SplitTicketRuleService())->applyNumberRules($ticket);
    }

    /**
     * 云控在线 → 开启；离线 → 关闭；工单关闭时一律关闭
     */
    public static function resolveSwitchStatus(Ticket $ticket, string $platformStatus): string
    {
        if ((string) ($ticket['status'] ?? 'hidden') !== 'normal') {
            return 'hidden';
        }

        return $platformStatus === 'online' ? 'normal' : 'hidden';
    }

    /**
     * @param Number $row
     */
    private function updateExistingNumber(
        Ticket $ticket,
        $row,
        string $platformStatus,
        int $newFollowers
    ): void {
        $update = [
            'platform_status' => $platformStatus,
            'updatetime'      => time(),
        ];

        if ((int) $row['manual_manage'] === 1) {
            Number::where('id', (int) $row['id'])->update($update);
            return;
        }

        $update['inbound_count'] = max(0, $newFollowers);
        Number::where('id', (int) $row['id'])->update($update);
    }

    private function insertNumber(
        Ticket $ticket,
        string $number,
        string $platformStatus,
        int $newFollowers
    ): void {
        $now = time();
        $data = [
            'admin_id'           => (int) $ticket['admin_id'],
            'split_link_id'      => (int) $ticket['split_link_id'],
            'ticket_name'        => (string) $ticket['ticket_name'],
            'number'             => $number,
            'number_type'        => (string) $ticket['number_type'],
            'number_type_custom' => (string) ($ticket['number_type_custom'] ?? ''),
            'visit_count'        => 0,
            'inbound_count'      => max(0, $newFollowers),
            'manual_manage'      => 0,
            'platform_status'    => $platformStatus,
            'ratio_deferred'     => 0,
            'createtime'         => $now,
            'updatetime'         => $now,
        ];

        try {
            Db::name('split_number')->insert($data);
        } catch (\Throwable $e) {
            $exists = Number::where('split_link_id', (int) $ticket['split_link_id'])
                ->where('ticket_name', (string) $ticket['ticket_name'])
                ->where('number', $number)
                ->find();
            if ($exists) {
                $this->updateExistingNumber($ticket, $exists, $platformStatus, $newFollowers);
            }
        }
    }

    /**
     * 统一号码为字符串（云控 API 可能返回 int）
     */
    private static function normalizeNumber($value): string
    {
        if ($value === null || $value === '') {
            return '';
        }
        return trim((string) $value);
    }

    /**
     * 汇总工单进线人数（仅开启状态的号码）
     */
    public function sumInboundForTicket(Ticket $ticket): int
    {
        $sum = Number::where('admin_id', (int) $ticket['admin_id'])
            ->where('split_link_id', (int) $ticket['split_link_id'])
            ->where('ticket_name', (string) $ticket['ticket_name'])
            ->where('status', 'normal')
            ->sum('inbound_count');
        return (int) $sum;
    }
}
