<?php

declare(strict_types=1);

namespace app\common\service;

use app\admin\model\split\Link;
use think\Exception;

/**
 * 分流链接码生成服务
 */
class SplitLinkCodeService
{
    private const CODE_LENGTH = 9;

    private const CHARSET = 'abcdefghijklmnopqrstuvwxyz';

    private const MAX_ATTEMPTS = 50;

    /**
     * 规范化链接码（小写、去空格）
     */
    public static function normalize(string $code): string
    {
        return strtolower(trim($code));
    }

    /**
     * 是否为合法 9 位小写字母链接码
     */
    public static function isValidFormat(string $code): bool
    {
        return (bool) preg_match('/^[a-z]{9}$/', $code);
    }

    /**
     * 链接码是否未被占用
     */
    public static function isAvailable(string $code, int $excludeId = 0): bool
    {
        $code = self::normalize($code);
        $query = Link::where('link_code', $code);
        if ($excludeId > 0) {
            $query->where('id', '<>', $excludeId);
        }
        return !$query->find();
    }

    /**
     * 生成唯一 9 位小写字母链接码
     *
     * @throws Exception
     */
    public function generateUnique(): string
    {
        for ($i = 0; $i < self::MAX_ATTEMPTS; $i++) {
            $code = $this->generateRandom();
            if (!Link::where('link_code', $code)->find()) {
                return $code;
            }
        }
        throw new Exception('分流链接生成失败，请稍后重试');
    }

    private function generateRandom(): string
    {
        $chars = self::CHARSET;
        $max = strlen($chars) - 1;
        $code = '';
        for ($i = 0; $i < self::CODE_LENGTH; $i++) {
            $code .= $chars[random_int(0, $max)];
        }
        return $code;
    }
}
