import os
import subprocess
import sys
import requests
from pathlib import Path
import json
import time

APP_PATH = os.path.dirname(sys.executable) if getattr(sys, 'frozen', False) else os.path.dirname(__file__)


class ApplicationApi:
    def __init__(self, api_url: str, api_key: str, application_name: str):
        self.api_url = api_url
        self.api_key = api_key
        self.application_name = application_name

    def method(self, http_method: str, method: str, data=None, files=None) -> dict:
        url = self.api_url + f'/{self.application_name}/{method}'
        headers = {'Authorization': self.api_key}
        return requests.request(http_method, url, headers=headers, data=data, files=files).json()

    def get_current_version(self):
        response = self.method('GET', 'version')
        return response.get('latest_version')

    def upload(self, version: str, file_path: str):
        data = {'version': version}
        files = {'file': open(file_path, 'rb')}
        return self.method('POST', 'upload', data=data, files=files)


def find_latest_modified_file(path, file_extension='*.py'):
    """ Находит файл с самой поздней датой изменения в указанной директории. """

    app_path = Path(path)
    files = app_path.glob(file_extension)
    max_time_file = max(files, key=lambda file: file.stat().st_atime, default=None)

    return max_time_file


def parse_version(version_str):
    """Преобразует строку версии в кортеж чисел."""
    return tuple(map(int, version_str.split('.')))


def is_valid_version(new_version, current_version):
    if not current_version: return bool(parse_version(new_version))
    """Проверяет, является ли новая версия больше текущей."""
    return parse_version(new_version) > parse_version(current_version)


def prompt_new_version(current_version, app_name):
    print(f"Current version of {app_name} is \"{current_version}\".")
    print("Please specify the new version (greater than current) in the format: major.minor.patch (e.g., 1.2.3)")
    while True:
        new_version = input("New version: ")
        if new_version and is_valid_version(new_version, current_version):
            return new_version
        else:
            print("Invalid version, it must be greater than the current version. Please try again.")


def update_version_in_expo(version: str):
    file_path = os.path.join(APP_PATH, 'app.json')
    with open(file_path, 'r+') as config_file:
        data = json.loads(config_file.read())
        data['expo']['version'] = version
        config_file.seek(0)
        config_file.write(json.dumps(data, indent=2, ensure_ascii=False))
        config_file.close()


def main():
    # API_URL = 'http://192.168.1.101:5000/application'
    API_URL = 'https://assemblr.denco.store/application'
    API_KEY = 'AF9A20DD9264C134CDA0ADACED834368'
    APPLICATION_NAME = 'assemblr'

    BUILD_COMMAND = 'npx expo prebuild && eas build -p android --profile preview --local'
    application_api = ApplicationApi(api_url=API_URL, api_key=API_KEY, application_name=APPLICATION_NAME)
    current_version = application_api.get_current_version()
    new_version = prompt_new_version(current_version, APPLICATION_NAME)
    update_version_in_expo(new_version)

    print('Starting building...')
    subprocess.run(BUILD_COMMAND, shell=True, text=True, capture_output=False)
    print('Build ended successfully.')
    apk_file = find_latest_modified_file(APP_PATH, '*.apk')
    if not apk_file:
        print(f'Failed to find the update APK file in the directory: {APP_PATH}')
        return

    # Получение времени последней модификации файла
    last_modified_time = apk_file.stat().st_atime
    formatted_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(last_modified_time))
    print(f'The APK file "{apk_file.name}" was last modified on: {formatted_time}')

    # Запрос подтверждения у пользователя
    user_confirmation = input("Are you sure you want to upload this update? (yes/no): ")
    if user_confirmation.lower() != 'yes':
        print("Upload cancelled.")
        return

    upload_response = application_api.upload(new_version, str(apk_file))
    error = upload_response.get('error')
    if error:
        print(f"Error occurred while trying to upload the update: {error}")
        return

    filename = upload_response.get('filename')
    version = upload_response.get('version')
    print(f"Update version '{version}' successfully uploaded. File name: '{filename}'.")


if __name__ == '__main__':
    main()
