import math
from io import BytesIO
from time import sleep
import os

import cv2
import numpy as np

from PIL import Image
from selenium.webdriver.common.actions.wheel_input import ScrollOrigin
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains

def generateURL(lat=49.103814, lon=55.794258, zoom=10):
    return f"https://yandex.ru/maps/43/kazan/?l=sat&ll={lat}%2C{lon}&z={zoom}"

class YandexMap:
    def __init__(self):
        options = webdriver.ChromeOptions()
        # options.add_experimental_option("detach", True)
        self.driver = webdriver.Chrome(options)
        self.driver.get(generateURL())
        sleep(2)

        action = ActionChains(self.driver)

        # Закрытие левой панели
        action.click(self.driver.find_element(By.CLASS_NAME, 'sidebar-toggle-button'))
        action.perform()

        self.driver.execute_script("arguments[0].remove();", self.driver.find_element(By.XPATH, "//div[@data-chunk='header']"))
        self.driver.execute_script("arguments[0].remove();", self.driver.find_element(By.XPATH, "//div[@class='sidebar-toggle-button _collapsed _name_home']"))
        self.driver.execute_script("arguments[0].remove();", self.driver.find_element(By.XPATH, "//nav[@class='map-controls']"))
        self.driver.execute_script("arguments[0].remove();", self.driver.find_element(By.XPATH, "//footer"))

        sleep(0.2)

    def save_photo(self, filename: str) -> bytes:
        return self.driver.save_screenshot(filename)

    def destroy(self):
        self.driver.close()
    
    def get_size(self) -> tuple[int, int]:
        html = self.driver.find_element(By.TAG_NAME, 'html')
        return (html.size['width'], html.size['height'])

    def scroll(self, x: float, y: float, count: int = 1, inner_zoom: bool = True):
        html = self.driver.find_element(By.TAG_NAME, 'html')

        x_offset = (x - 0.5) * html.size['width']
        y_offset = (y - 0.5) * html.size['height']
        action = ActionChains(self.driver)

        for i in range(count-1):
            action.scroll_from_origin(ScrollOrigin(html, int(x_offset), int(y_offset)), 0, -100 if inner_zoom else 100)
            action.perform()
            if i != count - 1:
                sleep(0.25)

    def make_as_center(self, x: float, y: float):
        html = self.driver.find_element(By.TAG_NAME, 'html')

        action = ActionChains(self.driver)
        action.move_to_element_with_offset(html, 0, 0)
        action.click_and_hold()

        dx = (x - 0.5) * self.get_size()[0]
        dy = (0.5 - y) * self.get_size()[1]
        print(dx, dy)
        action.move_by_offset(-dx, dy)
        action.release()
        action.perform()

    def make_screenshot(self, x: float, y: float, width: float, height: float) -> cv2.typing.MatLike:
        # Сохраняем скриншот
        self.save_photo("temp.png")
        
        # Загружаем изображение
        image = cv2.imread("temp.png")
        
        if image is None:
            raise ValueError("Не удалось загрузить изображение temp.png")
        
        # Получаем размеры исходного изображения
        img_height, img_width = image.shape[:2]
        
        # Преобразуем относительные координаты в абсолютные пиксели
        center_x = int(x * img_width)
        center_y = int(y * img_height)
        crop_width = int(width * img_width)
        crop_height = int(height * img_height)
        
        # Вычисляем координаты прямоугольника для кадрирования
        x1 = max(0, center_x - crop_width // 2)
        y1 = max(0, center_y - crop_height // 2)
        x2 = min(img_width, center_x + crop_width // 2)
        y2 = min(img_height, center_y + crop_height // 2)
        
        # Проверяем, что прямоугольник имеет положительные размеры
        if x2 <= x1 or y2 <= y1:
            raise ValueError("Некорректные размеры для кадрирования")
        
        # Кадрируем изображение
        cropped_image = image[y1:y2, x1:x2]
        
        # Если нужно вернуть изображение как результат функции:
        return cropped_image