import httpx
import random
import asyncio
import ddddocr
from PIL import Image
from io import BytesIO
from loguru import logger
from playwright.async_api import Page, Response, async_playwright


class AwemeBrowser:

    def __init__(self, session: str, headless: bool = False):
        self.x = 0
        self.y = ""
        self.url1 = ""
        self.url2 = ""
        self.tag = False
        self._session = session
        self._headless = headless
        self.ocr = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)

    async def login(self, page: Page, username) -> None:
        page.on("response", self.on_response)

        await page.goto('https://doujia.douyin.com/login')
        await page.wait_for_timeout(self.wait_random)
        if "扫码登录" not in await page.content():
            logger.info("账号={}, 正常在线".format(username))
        else:
            await page.click('li:has-text("验证码登录")')
            # 清空输入框
            await page.evaluate('document.querySelector(".web-login-normal-input__input").value=""')
            await page.evaluate('document.querySelector(".web-login-button-input__input").value=""')
            # 账号密码登录
            await page.wait_for_timeout(self.wait_random)
            await page.type(selector=".web-login-normal-input__input", text=username, delay=100)
            # await page.type(selector=".web-login-button-input__input", text=password, delay=100)
            await page.wait_for_timeout(self.wait_random)
            await page.click('span:has-text("获取验证码")')
            await page.wait_for_timeout(self.wait_random)
            num = 1
            while True:
                logger.warning("当前滑动次数: {}".format(num))

                distance = await self.get_distance()

                tracks = self.get_tracks(distance)

                new_frame = page.frame_locator('#captcha_container > iframe')
                slide = new_frame.locator('.captcha-slider-btn')
                box = await slide.bounding_box()
                await page.mouse.move(box["x"] + box["width"] / 2, box["y"] + box["height"] / 2)
                await page.mouse.down()
                x = box["x"] + box["width"] / 2
                for track in tracks:
                    x += track
                    await page.mouse.move(x, box["y"])
                    await asyncio.sleep(random.uniform(0.005, 0.02))
                await page.mouse.up()
                await page.wait_for_timeout(self.wait_random)
                num = num + 1
                if num > 5 or self.tag:
                    break
                await page.wait_for_timeout(self.wait_random)

    @property
    def wait_random(self):
        return random.randint(1000, 3000)

    async def on_response(self, response: Response):
        if "https://verify.zijieapi.com/captcha/get" in response.url:
            result = await response.json()
            data = result.get("data")
            picture = data.get("question")
            self.y = picture.get("tip_y")
            self.url1 = picture.get("url1")
            self.url2 = picture.get("url2")

        if "https://verify.zijieapi.com/captcha/verify" in response.url:
            result = await response.json()
            if result.get("code") == 200:
                logger.success("滑块通过, res={}".format(result))
                self.tag = True

    async def get_distance(self):
        async with httpx.AsyncClient() as session:
            response_1 = await session.get(self.url1)
            response_2 = await session.get(self.url2)
        image = Image.open(BytesIO(response_1.content))
        width, height = image.size
        sub_images = []
        for i in range(6):
            left = (i * width) // 6
            right = ((i + 1) * width) // 6
            sub_image = image.crop((left, 0, right, height))
            sub_images.append(sub_image)

        order = [1, 5, 4, 2, 0, 3]
        new_images = [None] * 6
        for i in range(6):
            new_images[order[i]] = sub_images[i]

        merged_image = Image.new('RGB', (width, height))
        for i in range(6):
            left = (i * width) // 6
            right = ((i + 1) * width) // 6
            merged_image.paste(new_images[i], (left, 0))

        # 保存图片
        merged_image.save('logs/images/captcha_restored.png')
        img_byte = BytesIO()
        merged_image.save(img_byte, format='JPEG')
        url1_content = img_byte.getvalue()
        ocr_response = self.ocr.slide_match(response_2.content, url1_content)
        x = ocr_response['target'][0]
        logger.info(f"滑动的距离为: {x}, 高度为: {self.y}")
        return int(int(x) / 550 * 340) - 5

    def get_tracks(self, distance):
        track = []
        current = 0
        mid = distance * 4 / 5
        t = 0.2
        v = 1

        while current < distance:
            if current < mid:
                a = 4
            else:
                a = -3
            v0 = v
            v = v0 + a * t
            move = v0 * t + 1 / 2 * a * t * t
            current += move
            track.append(round(move))
        return track

    async def start(self, username):
        async with async_playwright() as pwt:
            browser = await pwt.chromium.launch_persistent_context(
                headless=self._headless,
                user_data_dir=self._session,
                args=["--start-maximized", '--disable-blink-features=AutomationControlled'],
                no_viewport=True  # 窗口最大化
            )
            await browser.add_init_script(path="logs/js/stealth.min.js")
            page = await browser.new_page()
            await self.login(page=page, username=username)


async def main(username):
    b = AwemeBrowser(session=f"logs/session/{username}")
    await b.start(username)


asyncio.run(main("17682303516"))