import rumps
import threading
import time
from datetime import datetime, timedelta
from google.auth.transport.requests import Request
from google.oauth2.service_account import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth import default
from googleapiclient.discovery import build
import os
import sys
import pickle
from flask import Flask, render_template_string, request, jsonify
import socket

# Get app directory for file paths
def get_app_dir():
    """Get application directory - works in both dev and packaged app"""
    if getattr(sys, 'frozen', False):
        # Running as packaged app (py2app)
        # sys.executable is in Contents/MacOS/, we need Contents/Resources/
        app_dir = os.path.join(os.path.dirname(sys.executable), '..', 'Resources')
        app_dir = os.path.abspath(app_dir)
    else:
        # Running as script
        app_dir = os.path.dirname(os.path.abspath(__file__))
    return app_dir

def is_port_available(port):
    """Check if a port is available"""
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind(('127.0.0.1', port))
        sock.close()
        return True
    except OSError:
        return False

APP_DIR = get_app_dir()

class TimerApp(rumps.App):
    def __init__(self):
        super(TimerApp, self).__init__("Timer", title="⏱ 25:00")
        self.timer_lengths = [25, 5, 25, 5, 25, 5, 25, 20]  # Cycle pattern in minutes
        self.current_cycle_index = 0
        self.timer_length = self.timer_lengths[self.current_cycle_index] * 60
        self.time_remaining = self.timer_length
        self.timer_running = False
        self.timer_thread = None
        self.service = None
        self.timer_completed = False
        self.google_calendar_enabled = True
        
        # Tracking app uptime and elapsed time
        self.app_start_time = datetime.now()
        self.total_time_elapsed = 0  # Total time elapsed across all timers
        
        # Flask setup
        self.flask_app = Flask(__name__)
        self.setup_flask_routes()
        self.start_flask_server()
        
        self.authenticate_google_calendar()
        # Auto-start timer on app boot
        self.start_timer(None)
        
    def start_timer(self, _):
        if not self.timer_running:
            self.timer_running = True
            self.timer_completed = False
            self.timer_thread = threading.Thread(target=self.run_timer)
            self.timer_thread.daemon = True
            self.timer_thread.start()
    
    def setup_flask_routes(self):
        """Setup Flask routes for settings page"""
        
        @self.flask_app.route('/')
        def settings():
            html = '''<!DOCTYPE html>
            <html>
            <head>
                <title>Timer Settings</title>
                <style>
                    body { font-family: Arial; max-width: 700px; margin: 50px auto; padding: 20px; }
                    h1 { color: #FF9500; }
                    h2 { color: #333; border-bottom: 2px solid #FF9500; padding-bottom: 10px; }
                    .setting-group { margin: 30px 0; padding: 15px; background: #f9f9f9; border-radius: 8px; }
                    input { padding: 10px; font-size: 16px; width: 100%; box-sizing: border-box; }
                    button { padding: 10px 20px; font-size: 16px; margin-top: 10px; background: #FF9500; color: white; border: none; border-radius: 5px; cursor: pointer; }
                    button:hover { background: #E68900; }
                    .toggle { display: flex; align-items: center; gap: 10px; }
                    .toggle input[type="checkbox"] { width: 20px; height: 20px; cursor: pointer; }
                    .status { margin-top: 20px; padding: 15px; background: #f0f0f0; border-radius: 8px; }
                    .status p { margin: 10px 0; }
                    .error { color: red; }
                    .success { color: green; }
                    .message { margin-top: 10px; padding: 10px; border-radius: 5px; }
                </style>
            </head>
            <body>
                <h1>⏱ Timer Settings</h1>
                
                <div class="setting-group">
                    <h2>Current Timer Length</h2>
                    <p>Set the length for the current timer (in minutes)</p>
                    <input type="number" id="timer_length" min="1" placeholder="25">
                    <button onclick="updateTimerLength()">Update Current Timer</button>
                </div>
                
                <div class="setting-group">
                    <h2>Timer Cycle Pattern</h2>
                    <p>Enter comma-separated values in minutes (e.g., 25,5,25,5,25,5,25,20)</p>
                    <input type="text" id="pattern" placeholder="25,5,25,5,25,5,25,20">
                    <button onclick="updatePattern()">Update Pattern</button>
                </div>
                
                <div class="setting-group">
                    <h2>Google Calendar</h2>
                    <div class="toggle">
                        <input type="checkbox" id="calendar_toggle" onchange="toggleCalendar()">
                        <label for="calendar_toggle">Create calendar events when timers complete</label>
                    </div>
                </div>
                
                <div class="status">
                    <h2>App Status</h2>
                    <p><strong>App Started:</strong> <span id="app_started"></span></p>
                    <p><strong>Total Time Elapsed:</strong> <span id="total_elapsed"></span></p>
                    <p><strong>Timer Running:</strong> <span id="timer_status"></span></p>
                    <p><strong>Time Remaining:</strong> <span id="time_remaining"></span></p>
                    <p><strong>Current Pattern:</strong> <span id="current_pattern"></span></p>
                </div>
                
                <div id="message"></div>
                
                <script>
                    function loadSettings() {
                        fetch('/api/settings')
                            .then(r => r.json())
                            .then(data => {
                                document.getElementById('pattern').value = data.pattern;
                                document.getElementById('timer_length').value = data.timer_length_minutes;
                                document.getElementById('current_pattern').innerText = data.pattern;
                                document.getElementById('timer_status').innerText = data.running ? '✓ Running' : '✗ Paused';
                                document.getElementById('time_remaining').innerText = data.time_remaining;
                                document.getElementById('app_started').innerText = data.app_started;
                                document.getElementById('total_elapsed').innerText = data.total_elapsed;
                                document.getElementById('calendar_toggle').checked = data.calendar_enabled;
                            });
                    }
                    
                    function updateTimerLength() {
                        const length = document.getElementById('timer_length').value;
                        fetch('/api/update_timer_length', {
                            method: 'POST',
                            headers: {'Content-Type': 'application/json'},
                            body: JSON.stringify({minutes: parseInt(length)})
                        })
                        .then(r => r.json())
                        .then(data => {
                            const msg = document.getElementById('message');
                            if (data.success) {
                                msg.innerHTML = '<div class="message success">✓ Timer length updated to ' + length + ' minutes!</div>';
                                loadSettings();
                            } else {
                                msg.innerHTML = '<div class="message error">✗ ' + data.error + '</div>';
                            }
                            setTimeout(() => msg.innerHTML = '', 3000);
                        });
                    }
                    
                    function updatePattern() {
                        const pattern = document.getElementById('pattern').value;
                        fetch('/api/update_pattern', {
                            method: 'POST',
                            headers: {'Content-Type': 'application/json'},
                            body: JSON.stringify({pattern: pattern})
                        })
                        .then(r => r.json())
                        .then(data => {
                            const msg = document.getElementById('message');
                            if (data.success) {
                                msg.innerHTML = '<div class="message success">✓ Pattern updated!</div>';
                                loadSettings();
                            } else {
                                msg.innerHTML = '<div class="message error">✗ ' + data.error + '</div>';
                            }
                            setTimeout(() => msg.innerHTML = '', 3000);
                        });
                    }
                    
                    function toggleCalendar() {
                        const enabled = document.getElementById('calendar_toggle').checked;
                        fetch('/api/toggle_calendar', {
                            method: 'POST',
                            headers: {'Content-Type': 'application/json'},
                            body: JSON.stringify({enabled: enabled})
                        })
                        .then(r => r.json())
                        .then(data => {
                            const msg = document.getElementById('message');
                            if (data.success) {
                                msg.innerHTML = '<div class="message success">✓ Calendar events ' + (enabled ? 'enabled' : 'disabled') + '!</div>';
                                setTimeout(() => msg.innerHTML = '', 2000);
                            }
                        });
                    }
                    
                    setInterval(loadSettings, 1000);
                    loadSettings();
                </script>
            </body>
            </html>'''
            return render_template_string(html)
        
        @self.flask_app.route('/api/settings')
        def get_settings():
            """Get current settings"""
            return jsonify({
                'pattern': ','.join(map(str, self.timer_lengths)),
                'timer_length_minutes': self.timer_length // 60,
                'running': self.timer_running,
                'time_remaining': self.format_time(self.time_remaining),
                'app_started': self.app_start_time.strftime('%Y-%m-%d %H:%M:%S'),
                'total_elapsed': self.format_time(self.total_time_elapsed),
                'calendar_enabled': self.google_calendar_enabled
            })
        
        @self.flask_app.route('/api/update_timer_length', methods=['POST'])
        def update_timer_length():
            """Update current timer length"""
            try:
                data = request.json
                minutes = data.get('minutes', 0)
                
                if minutes <= 0:
                    return jsonify({'success': False, 'error': 'Timer length must be positive'})
                
                # Stop old timer
                self.timer_running = False
                time.sleep(0.3)  # Wait for old thread to stop
                
                self.timer_length = minutes * 60
                self.time_remaining = self.timer_length
                self.timer_completed = False
                self.update_title()
                
                # Auto-start timer
                self.timer_running = True
                self.timer_thread = threading.Thread(target=self.run_timer)
                self.timer_thread.daemon = True
                self.timer_thread.start()
                
                return jsonify({'success': True})
            except (ValueError, TypeError):
                return jsonify({'success': False, 'error': 'Invalid timer length'})
        
        @self.flask_app.route('/api/update_pattern', methods=['POST'])
        def update_pattern():
            """Update timer pattern"""
            try:
                data = request.json
                pattern = data.get('pattern', '')
                
                lengths = [int(x.strip()) for x in pattern.split(',')]
                if any(x <= 0 for x in lengths):
                    return jsonify({'success': False, 'error': 'All values must be positive'})
                
                self.timer_lengths = lengths
                self.timer_running = False
                self.current_cycle_index = 0
                self.timer_length = self.timer_lengths[self.current_cycle_index] * 60
                self.time_remaining = self.timer_length
                self.timer_completed = False
                self.update_title()
                
                return jsonify({'success': True})
            except ValueError:
                return jsonify({'success': False, 'error': 'Invalid format. Use: 25,5,25,5'})
        
        @self.flask_app.route('/api/toggle_calendar', methods=['POST'])
        def toggle_calendar():
            """Toggle Google Calendar event creation"""
            data = request.json
            self.google_calendar_enabled = data.get('enabled', True)
            return jsonify({'success': True})
    
    def start_flask_server(self):
        """Run Flask in background thread"""
        thread = threading.Thread(
            target=self.flask_app.run,
            kwargs={'host': '127.0.0.1', 'port': 5000, 'debug': False, 'use_reloader': False, 'threaded': True},
            daemon=True
        )
        thread.start()
    
    def format_time(self, seconds):
        """Format seconds to MM:SS or HH:MM:SS for large durations"""
        if seconds >= 0:
            if seconds >= 3600:
                hours = seconds // 3600
                mins = (seconds % 3600) // 60
                secs = seconds % 60
                return f"{hours:02d}:{mins:02d}:{secs:02d}"
            else:
                mins, secs = divmod(seconds, 60)
                return f"{mins:02d}:{secs:02d}"
        else:
            abs_sec = abs(seconds)
            mins, secs = divmod(abs_sec, 60)
            return f"-{mins:02d}:{secs:02d}"
    
    @rumps.clicked("Next Cycle")
    def next_cycle(self, _):
        self.timer_running = False
        time.sleep(0.3)  # Wait for old thread to stop
        self.timer_completed = False
        self.current_cycle_index = (self.current_cycle_index + 1) % len(self.timer_lengths)
        self.timer_length = self.timer_lengths[self.current_cycle_index] * 60
        self.time_remaining = self.timer_length
        self.update_title()
        # Auto-start timer
        self.start_timer(None)
    
    @rumps.clicked("Settings")
    def open_settings(self, _):
        """Open settings in browser with retry logic"""
        def open_browser():
            for attempt in range(5):
                if is_port_available(5000):
                    time.sleep(0.5)  # Wait for Flask to fully start
                os.system('open http://127.0.0.1:5000')
                break
                time.sleep(0.5)
        
        thread = threading.Thread(target=open_browser, daemon=True)
        thread.start()
    
    @rumps.clicked("Pause Timer")
    def pause_timer(self, _):
        if self.timer_running:
            # Pause the timer
            self.timer_running = False
        elif not self.timer_running and self.time_remaining > 0:
            # Unpause the timer
            self.timer_running = True
            self.timer_thread = threading.Thread(target=self.run_timer)
            self.timer_thread.daemon = True
            self.timer_thread.start()
    
    @rumps.clicked("Reset Timer")
    def reset_timer(self, _):
        self.timer_running = False
        self.timer_completed = False
        self.time_remaining = self.timer_length
        self.update_title()

    def authenticate_google_calendar(self):
        """Authenticate with Google Calendar API"""
        SCOPES = ['https://www.googleapis.com/auth/calendar']
        creds = None
        
        # Use absolute paths
        token_file = os.path.join(APP_DIR, 'token.pickle')
        credentials_file = os.path.join(APP_DIR, 'credentials.json')
        
        # Load existing token
        if os.path.exists(token_file):
            with open(token_file, 'rb') as token:
                creds = pickle.load(token)
        
        # Authenticate if no valid token
        if not creds or not creds.valid:
            if creds and creds.expired and creds.refresh_token:
                creds.refresh(Request())
            else:
                if not os.path.exists(credentials_file):
                    rumps.alert(
                        "Google Calendar Setup",
                        "Please create a credentials.json file with your Google Calendar API credentials."
                    )
                    return
                flow = InstalledAppFlow.from_client_secrets_file(
                    credentials_file, SCOPES)
                creds = flow.run_local_server(port=0)
            
            # Save token for future runs
            with open(token_file, 'wb') as token:
                pickle.dump(creds, token)
        
        self.service = build('calendar', 'v3', credentials=creds)
    
    def get_event_name(self, timer_length):
        """Determine event name based on timer length"""
        if timer_length == 25:
            return "work"
        elif timer_length == 5:
            return "break"
        elif timer_length == 20:
            return "long break"
        else:
            return f"timer ({timer_length} min)"
    
    def create_calendar_event(self, event_name, duration_minutes):
        """Create event in Google Calendar"""
        if not self.google_calendar_enabled or not self.service:
            return
        
        try:
            now = datetime.utcnow()
            start_time = now
            end_time = now + timedelta(minutes=duration_minutes)
            
            event = {
                'summary': event_name,
                'start': {
                    'dateTime': start_time.isoformat() + 'Z',
                    'timeZone': 'America/Los_Angeles',
                },
                'end': {
                    'dateTime': end_time.isoformat() + 'Z',
                    'timeZone': 'America/Los_Angeles',
                },
            }
            
            created_event = self.service.events().insert(
                calendarId='primary',
                body=event
            ).execute()
            
            print(f"Event created: {created_event['htmlLink']}")
        except Exception as e:
            print(f"Error creating calendar event: {e}")
    
    def run_timer(self):
        while self.timer_running:
            time.sleep(1)
            if self.timer_running:
                self.time_remaining -= 1
                self.total_time_elapsed += 1
                self.update_title()
                
                # Trigger completion logic only once when hitting 0
                if self.time_remaining == 0 and not self.timer_completed:
                    self.timer_completed = True
                    timer_name = self.get_event_name(self.timer_length // 60)
                    
                    rumps.notification(
                        title="Timer Complete!",
                        subtitle="Time's up!",
                        message=f"Your {timer_name} session has finished."
                    )
                    
                    # Create calendar event for completed timer
                    self.create_calendar_event(timer_name, self.timer_length // 60)
                    
                    # Advance to next cycle
                    self.current_cycle_index = (self.current_cycle_index + 1) % len(self.timer_lengths)
                    self.timer_length = self.timer_lengths[self.current_cycle_index] * 60
    
    def update_title(self):
        if self.time_remaining >= 0:
            minutes = self.time_remaining // 60
            seconds = self.time_remaining % 60
            self.title = f"⏱ {minutes:02d}:{seconds:02d}"
        else:
            # Handle negative time (counting up from 0)
            abs_time = abs(self.time_remaining)
            minutes = abs_time // 60
            seconds = abs_time % 60
            self.title = f"⏱ -{minutes:02d}:{seconds:02d}"


if __name__ == "__main__":
    app = TimerApp()
    app.run()
