<?php

declare(strict_types=1);

namespace app\common\service;

use app\admin\model\split\Number;
use app\admin\model\split\Ticket;

/**
 * 工单与号码业务规则（单号上限、下号比率、时间窗口、完成量自动开关）
 */
class SplitTicketRuleService
{
    /**
     * 同步后应用全部规则并写回工单/号码
     */
    public function applyAfterSync(Ticket $ticket, int $completeCount): void
    {
        $this->applyTicketStatusRules($ticket, $completeCount);
        $fresh = Ticket::get((int) $ticket['id']);
        if ($fresh) {
            if ((string) $fresh['status'] === 'hidden') {
                $this->cascadeTicketClosedToNumbers($fresh);
            }
            $this->applyNumberRules($fresh);
        }
    }

    /**
     * 同步流程：工单因时间/完成量等原因关闭时，联动关闭非手动号码
     */
    public function cascadeTicketClosedToNumbers(Ticket $ticket): void
    {
        if ((string) ($ticket['status'] ?? 'hidden') !== 'hidden') {
            return;
        }
        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('manual_manage', 0)
            ->update([
                'status'     => 'hidden',
                'updatetime' => time(),
            ]);
    }

    /**
     * 手动切换工单状态时，联动非手动管理的号码
     */
    public function syncNumbersWithTicketStatus(Ticket $ticket): void
    {
        $ticketStatus = (string) ($ticket['status'] ?? 'hidden');
        if ($ticketStatus === 'hidden') {
            $this->cascadeTicketClosedToNumbers($ticket);
            return;
        }
        $this->applyNumberRules($ticket);
    }

    /**
     * 工单处于开启状态时，将云控在线的非手动号码设为开启
     *
     * @deprecated 请使用 applyNumberRules（会校验单号上限/下号比率）
     */
    public function syncOnlineNumbersWhenTicketOpen(Ticket $ticket): void
    {
        $this->applyNumberRules($ticket);
    }

    /**
     * 单号上限、下号比率、云控在线状态、工单开关综合决定号码状态
     */
    public function applyNumberRules(Ticket $ticket): void
    {
        $orderLimit = (int) ($ticket['order_limit'] ?? 0);
        $assignRatio = (int) ($ticket['assign_ratio'] ?? 0);

        $numbers = Number::where('admin_id', (int) $ticket['admin_id'])
            ->where('split_link_id', (int) $ticket['split_link_id'])
            ->where('ticket_name', (string) $ticket['ticket_name'])
            ->select();

        foreach ($numbers as $number) {
            $visitCount = (int) $number['visit_count'];
            $inboundCount = (int) $number['inbound_count'];
            $lastVisit = (int) ($number['last_sync_visit_count'] ?? 0);
            $lastInbound = (int) ($number['last_sync_inbound_count'] ?? 0);
            $streak = (int) ($number['no_inbound_click_streak'] ?? 0);

            if ($visitCount > $lastVisit && $inboundCount <= $lastInbound) {
                $streak += ($visitCount - $lastVisit);
            } elseif ($inboundCount > $lastInbound) {
                $streak = 0;
            }

            $update = [
                'no_inbound_click_streak' => $streak,
                'last_sync_visit_count'   => $visitCount,
                'last_sync_inbound_count' => $inboundCount,
                'updatetime'              => time(),
            ];

            // 手动管理（含用户手动关闭）的号码：仅更新统计字段，不改状态
            if ((int) $number['manual_manage'] === 1) {
                Number::where('id', (int) $number['id'])->update($update);
                continue;
            }

            $update['status'] = $this->resolveAutomatedStatus(
                $ticket,
                (string) ($number['platform_status'] ?? 'unknown'),
                $inboundCount,
                $streak,
                $orderLimit,
                $assignRatio
            );

            Number::where('id', (int) $number['id'])->update($update);
        }
    }

    /**
     * 非手动管理号码的自动开关判定
     */
    private function resolveAutomatedStatus(
        Ticket $ticket,
        string $platformStatus,
        int $inboundCount,
        int $streak,
        int $orderLimit,
        int $assignRatio
    ): string {
        if ((string) ($ticket['status'] ?? 'hidden') !== 'normal') {
            return 'hidden';
        }
        if ($platformStatus !== 'online') {
            return 'hidden';
        }
        if ($orderLimit > 0 && $inboundCount >= $orderLimit) {
            return 'hidden';
        }
        if ($assignRatio > 0 && $streak >= $assignRatio) {
            return 'hidden';
        }

        return 'normal';
    }

    /**
     * 完成量、时间窗口决定工单开关（定时与手动同步均适用）
     */
    public function applyTicketStatusRules(Ticket $ticket, int $completeCount): void
    {
        $status = $this->resolveTicketStatus($ticket, $completeCount);
        if ($status !== (string) ($ticket['status'] ?? 'hidden')) {
            Ticket::where('id', (int) $ticket['id'])->update([
                'status'     => $status,
                'updatetime' => time(),
            ]);
            $ticket['status'] = $status;
        }
    }

    /**
     * 是否处于允许同步/开启的时间窗口
     */
    public function isWithinTimeWindow(Ticket $ticket, ?int $now = null): bool
    {
        $now = $now ?? time();
        $start = $ticket['start_time'] ?? null;
        $end = $ticket['end_time'] ?? null;
        if ($start !== null && $start !== '' && (int) $start > 0 && $now < (int) $start) {
            return false;
        }
        if ($end !== null && $end !== '' && (int) $end > 0 && $now > (int) $end) {
            return false;
        }
        return true;
    }

    private function resolveTicketStatus(Ticket $ticket, int $completeCount): string
    {
        if (!$this->isWithinTimeWindow($ticket)) {
            return 'hidden';
        }

        $ticketTotal = (int) ($ticket['ticket_total'] ?? 0);
        if ($ticketTotal > 0) {
            return $completeCount >= $ticketTotal ? 'hidden' : 'normal';
        }

        return 'normal';
    }
}
