<?php

declare(strict_types=1);

namespace app\admin\model\split;

use app\common\service\SplitSyncConfigService;
use think\Db;
use think\Model;

/**
 * 分流工单模型
 */
class Ticket extends Model
{
    protected $name = 'split_ticket';

    protected $autoWriteTimestamp = 'integer';

    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    protected $deleteTime = false;

    protected $append = [
        'ticket_type_text',
        'number_type_text',
        'link_code_text',
        'start_time_text',
        'end_time_text',
        'status_text',
        'click_count',
        'ticket_progress_text',
        'inbound_ratio_text',
        'sync_display_text',
        'sync_success_text',
        'sync_tooltip_text',
        'sync_auto_paused',
    ];

    /**
     * 工单类型
     *
     * @return array<string, string>
     */
    public function getTicketTypeList(): array
    {
        return [
            'xinghe'      => __('Ticket type xinghe'),
            'haiwang'     => __('Ticket type haiwang'),
            'taiji'       => __('Ticket type taiji'),
            'huojian'     => __('Ticket type huojian'),
            'ss_channel'  => __('Ticket type ss_channel'),
            'ss_customer' => __('Ticket type ss_customer'),
            'yifafa'      => __('Ticket type yifafa'),
            'a2c'         => __('Ticket type a2c'),
            'ceo_scrm'    => __('Ticket type ceo_scrm'),
            'chatknow'    => __('Ticket type chatknow'),
            'whatshub'    => __('Ticket type whatshub'),
            'sihai'       => __('Ticket type sihai'),
        ];
    }

    /**
     * @return array<string, string>
     */
    public function getStatusList(): array
    {
        return [
            'normal' => __('Status normal'),
            'hidden' => __('Status hidden'),
        ];
    }

    /**
     * @return array<string, string>
     */
    public function getSyncStatusList(): array
    {
        return [
            'success' => __('Sync status success'),
            'error'   => __('Sync status error'),
            'pending' => __('Sync status pending'),
        ];
    }

    /**
     * 号码类型
     *
     * @return array<string, string>
     */
    public function getNumberTypeList(): array
    {
        return [
            'whatsapp' => 'Whatsapp',
            'telegram' => 'Telegram',
            'line'     => 'Line',
            'custom'   => __('Number type custom'),
        ];
    }

    /**
     * 关联分流链接
     */
    public function splitLink()
    {
        // IN 预载入：避免 eagerlyType=0(JOIN) 与列表 field 子查询冲突导致 SQL 1064
        return $this->belongsTo(Link::class, 'split_link_id', 'id', [], 'LEFT')->setEagerlyType(1);
    }

    /**
     * 列表子查询注入的点击数，无则按关联号码汇总
     *
     * @param mixed $value
     * @param array<string, mixed> $data
     */
    public function getClickCountAttr($value, $data): int
    {
        if (isset($data['click_count']) && $data['click_count'] !== '' && $data['click_count'] !== null) {
            return (int) $data['click_count'];
        }
        return self::sumVisitCountForTicket($data);
    }

    /**
     * 工单进度：完成数量 / 工单总量
     *
     * @param mixed $value
     * @param array<string, mixed> $data
     */
    public function getTicketProgressTextAttr($value, $data): string
    {
        $total = (int) ($data['ticket_total'] ?? 0);
        $complete = (int) ($data['complete_count'] ?? 0);
        if ($total <= 0) {
            return '0%';
        }
        $percent = round($complete / $total * 100, 2);
        return $percent . '%';
    }

    /**
     * 进线比例：进线人数 / 点击数（点击数=关联号码 visit_count 之和）
     *
     * @param mixed $value
     * @param array<string, mixed> $data
     */
    public function getInboundRatioTextAttr($value, $data): string
    {
        $clicks = $this->getClickCountAttr(null, $data);
        $inbound = (int) ($data['inbound_count'] ?? 0);
        if ($clicks <= 0) {
            return '—';
        }
        $percent = round($inbound / $clicks * 100, 2);
        return $percent . '%';
    }

    /**
     * 是否因连续失败暂停自动同步（工单仍为开启状态）
     *
     * @param array<string, mixed> $data
     */
    public static function isAutoSyncPaused(array $data): bool
    {
        if ((string) ($data['status'] ?? '') !== 'normal') {
            return false;
        }
        $threshold = SplitSyncConfigService::getFailPauseThreshold();
        if ($threshold <= 0) {
            return false;
        }
        return (int) ($data['sync_fail_count'] ?? 0) >= $threshold;
    }

    /**
     * 同步状态展示文案（列表列默认显示，异常详情见 tooltip）
     *
     * @param mixed $value
     * @param array<string, mixed> $data
     */
    public function getSyncDisplayTextAttr($value, $data): string
    {
        if (self::isAutoSyncPaused($data)) {
            $threshold = SplitSyncConfigService::getFailPauseThreshold();
            return sprintf((string) __('Sync display auto paused'), $threshold);
        }

        $status = (string) ($data['sync_status'] ?? 'pending');
        $online = (int) ($data['online_count'] ?? 0);
        if ($status === 'success') {
            return sprintf((string) __('Sync display success'), $online);
        }
        if ($status === 'pending') {
            return (string) __('Sync display pending');
        }
        return (string) __('Sync display error');
    }

    /**
     * 同步状态列 tooltip 完整说明
     *
     * @param mixed $value
     * @param array<string, mixed> $data
     */
    public function getSyncTooltipTextAttr($value, $data): string
    {
        $parts = [];
        if (self::isAutoSyncPaused($data)) {
            $threshold = SplitSyncConfigService::getFailPauseThreshold();
            $parts[] = sprintf(
                (string) __('Sync tooltip auto paused'),
                (int) ($data['sync_fail_count'] ?? 0),
                $threshold
            );
        }

        $message = trim((string) ($data['sync_message'] ?? ''));
        if ($message !== '') {
            $parts[] = (string) __('Sync tooltip error prefix') . $message;
        }

        return implode("\n", $parts);
    }

    /**
     * 是否暂停自动同步（供前端样式判断）
     *
     * @param mixed $value
     * @param array<string, mixed> $data
     */
    public function getSyncAutoPausedAttr($value, $data): bool
    {
        return self::isAutoSyncPaused($data);
    }

    /**
     * 最近一次同步成功时间及方式
     *
     * @param mixed $value
     * @param array<string, mixed> $data
     */
    public function getSyncSuccessTextAttr($value, $data): string
    {
        $ts = (int) ($data['sync_success_time'] ?? 0);
        if ($ts <= 0) {
            return '';
        }
        $timeText = date('Y-m-d H:i:s', $ts);
        $mode = (string) ($data['sync_success_mode'] ?? '');
        if ($mode === 'auto') {
            return $timeText . ' (' . (string) __('Sync mode auto') . ')';
        }
        if ($mode === 'manual') {
            return $timeText . ' (' . (string) __('Sync mode manual') . ')';
        }
        return $timeText;
    }

    public function setStartTimeAttr($value): ?int
    {
        return self::parseTimeValue($value);
    }

    public function setEndTimeAttr($value): ?int
    {
        return self::parseTimeValue($value);
    }

    public function setNumberTypeCustomAttr($value): string
    {
        return trim((string) $value);
    }

    public function setTicketTotalAttr($value): int
    {
        return max(0, (int) $value);
    }

    public function getTicketTypeTextAttr($value, $data): string
    {
        $key = (string) ($data['ticket_type'] ?? '');
        $list = $this->getTicketTypeList();
        return $list[$key] ?? $key;
    }

    public function getNumberTypeTextAttr($value, $data): string
    {
        $type = (string) ($data['number_type'] ?? '');
        if ($type === 'custom') {
            $custom = trim((string) ($data['number_type_custom'] ?? ''));
            return $custom !== '' ? $custom : (string) __('Number type custom');
        }
        $list = $this->getNumberTypeList();
        return $list[$type] ?? $type;
    }

    public function getLinkCodeTextAttr($value, $data): string
    {
        if ($value !== '' && $value !== null) {
            return (string) $value;
        }
        $linkId = (int) ($data['split_link_id'] ?? 0);
        if ($linkId <= 0) {
            return '';
        }
        $code = Link::where('id', $linkId)->value('link_code');
        return (string) $code;
    }

    public function getStartTimeTextAttr($value, $data): string
    {
        return self::formatTimeText($data['start_time'] ?? null);
    }

    public function getEndTimeTextAttr($value, $data): string
    {
        return self::formatTimeText($data['end_time'] ?? null);
    }

    public function getStatusTextAttr($value, $data): string
    {
        $key = (string) ($data['status'] ?? '');
        $list = $this->getStatusList();
        return $list[$key] ?? $key;
    }

    /**
     * 构建列表用 click_count 子查询 SQL 片段
     */
    public static function buildClickCountSubQuery(string $ticketTableAlias = ''): string
    {
        $ticketTable = (new self())->getTable();
        $numberTable = (new Number())->getTable();
        $t = $ticketTableAlias !== '' ? $ticketTableAlias : $ticketTable;
        return "(SELECT COALESCE(SUM(n.visit_count), 0) FROM `{$numberTable}` n "
            . "WHERE n.ticket_name = `{$t}`.ticket_name "
            . "AND n.split_link_id = `{$t}`.split_link_id "
            . "AND n.admin_id = `{$t}`.admin_id) AS click_count";
    }

    /**
     * @param array<string, mixed> $data
     */
    private static function sumVisitCountForTicket(array $data): int
    {
        $ticketName = (string) ($data['ticket_name'] ?? '');
        $linkId = (int) ($data['split_link_id'] ?? 0);
        $adminId = (int) ($data['admin_id'] ?? 0);
        if ($ticketName === '' || $linkId <= 0) {
            return 0;
        }
        $sum = Db::name('split_number')
            ->where('ticket_name', $ticketName)
            ->where('split_link_id', $linkId)
            ->where('admin_id', $adminId)
            ->sum('visit_count');
        return (int) $sum;
    }

    /**
     * @param mixed $value
     */
    private static function parseTimeValue($value): ?int
    {
        if ($value === '' || $value === null) {
            return null;
        }
        if (is_numeric($value)) {
            return (int) $value;
        }
        $ts = strtotime((string) $value);
        return $ts === false ? null : $ts;
    }

    /**
     * @param mixed $value
     */
    private static function formatTimeText($value): string
    {
        if ($value === '' || $value === null || !is_numeric($value)) {
            return '';
        }
        $ts = (int) $value;
        return $ts > 0 ? date('Y-m-d H:i:s', $ts) : '';
    }
}
