# main.py
import gc
gc.collect()

import time, machine
from logger import log
gc.collect()

import config_manager
gc.collect()

from wifi_manager import WiFiManager
gc.collect()

# <<< ИЗМЕНЕНО: импорт из пакета lib.web_server (если у тебя пакет)
# или from web_server import WebServer (если плоская структура)
from lib.web_server import WebServer
gc.collect()

def init_config():
	cfg = config_manager.load_config()
	if not cfg:
		log.warning("main", "Config not found. Creating default...")
		with open('config.defaults.json', 'r') as src, open('config.json', 'w') as dst:
			dst.write(src.read())
		cfg = config_manager.load_config()
	return cfg

def init_wifi(cfg):
	try:
		import network
		network.hostname(cfg.get("system", {}).get("device_name", "NoName"))
	except Exception:
		pass

	wifi_cfg = cfg.get("wifi", {})
	sta_cfg = {"ssid": wifi_cfg.get("ssid"), "password": wifi_cfg.get("password")}
	ap_cfg = {
		"ssid": wifi_cfg.get("ap_ssid", "CH340_AP"),
		"password": wifi_cfg.get("ap_password", "12345678"),
		"ip": wifi_cfg.get("ap_ip", "192.168.4.1")
	}

	wifi = WiFiManager()
	connected = False

	if sta_cfg["ssid"]:
		for attempt in range(3):
			log.info("wifi", f"Connecting to STA (Attempt {attempt + 1}/3)")
			connected = wifi.connect_sta(sta_cfg["ssid"], sta_cfg["password"])
			if connected: break
			time.sleep(2)

	if not connected:
		log.info("main", "Switching to AP mode")
		wifi.start_ap(ap_cfg["ssid"], ap_cfg["password"], ap_cfg["ip"])

	return wifi

def check_and_apply_ota(cfg):
	import uos, ujson, sys
	trigger_file = 'ota_trigger.json'
	
	try: uos.stat(trigger_file)
	except OSError: return False
	
	log.info("main", "OTA trigger found!")
	
	try:
		with open(trigger_file, 'r') as f:
			data = ujson.loads(f.read())
	except Exception as e:
		log.error("main", "Trigger read failed: " + str(e))
		try: uos.remove(trigger_file)
		except: pass
		return False

	status = data.get("status", "unknown")
	attempts = data.get("attempts", 0)
	max_attempts = data.get("max_attempts", 3)

	log.info("main", f"OTA status: {status}, attempts: {attempts}/{max_attempts}")

	if status == "completed":
		log.info("main", "OTA completed. Cleaning trigger.")
		try: uos.remove(trigger_file)
		except: pass
		return False

	elif status in ["pending", "downloading", "extracting", "applying", "error"]:
		attempts += 1
		if attempts >= max_attempts:
			log.error("main", "Max attempts reached. Aborting.")
			try: uos.remove(trigger_file)
			except: pass
			return False
		
		data["attempts"] = attempts
		data["status"] = "error"
		data["message"] = f"Retry after {status}"
		data["timestamp"] = int(time.time())
		
		try:
			with open(trigger_file, 'w') as f:
				f.write(ujson.dumps(data))
		except:
			try: uos.remove(trigger_file)
			except: pass
			return False

	log.info("main", "Starting OTA process...")
	gc.collect()
	
	try:
		from lib.ota.manager import OTAManager
		ota = OTAManager(config_manager)
		gc.collect()
		
		if status == "downloaded":
			log.info("main", "Status: downloaded. Loading manifest from disk...")
			if not ota.load_manifest_from_disk():
				log.error("main", "Manifest missing. Aborting.")
				return False
		else:
			log.info("main", "Fetching manifest from server...")
			res = ota.check_for_update()
			if not res.get('success'):
				log.error("main", "Fetch failed: " + str(res.get('error')))
				return False
		
		log.info("main", "Processing update...")
		ota.process_update()
			
	except Exception as e:
		log.error("main", "CRITICAL OTA ERROR:")
		sys.print_exception(e)
			
	return False

def main():
	print("\n" + "=" * 50 + "\nSystem startup\n" + "=" * 50)
	log.info("main", f"Free RAM after imports: {gc.mem_free()}")
	
	cfg = init_config()
	wifi = init_wifi(cfg)
	status = wifi.get_status()
	print(f"\nNetwork: {status['mode']} | IP: {status['ip']}")
	log.info("main", f"Free RAM after Wi-Fi: {gc.mem_free()}")
	
	check_and_apply_ota(cfg)
	gc.collect()
	
	server = WebServer(port = 80, status_callback = wifi.get_status, config_manager = config_manager)
	server.start()
	log.info("main", f"Web server ready. Open http://{status['ip']}")
	
	# <<< УБРАНО: блок предзагрузки (под .mpy не нужен)
	log.info("main", f"Free RAM in runtime: {gc.mem_free()}")
	print("=" * 50)
	
	counter = 0
	while True:
		server.poll()
		counter += 1
		if counter % 60 == 0:
			log.info("main", "Uptime: " + str(int(time.time() - server.start_time)) + "s")
		time.sleep(0.5)

if __name__ == "__main__":
	main()