"""Click CLI for ADS1115 ADC device."""

import click
import json
from ..service import get_service, ADS1115Config, reset_service


@click.group()
@click.option('--mock', is_flag=True, help='Force mock mode (no hardware)')
@click.option('--address', default='0x48', help='I2C address (default: 0x48)')
@click.option('--gain', default=1.0, type=float, help='ADC gain (default: 1.0)')
@click.pass_context
def cli(ctx, mock, address, gain):
    """piADC CLI - Control and read data from ADS1115 device."""
    ctx.ensure_object(dict)
    
    # Set environment for mock mode
    if mock:
        import os
        os.environ['ADS1115_MOCK'] = 'true'
    
    # Parse address
    addr = int(address, 16) if address.startswith('0x') else int(address)
    
    config = ADS1115Config(
        i2c_address=addr,
        gain=gain
    )
    
    service = get_service()
    if service._adc is None:
        service.config = config
        service.initialize()
    
    ctx.obj['service'] = service


@cli.command()
@click.pass_context
def status(ctx):
    """Show device status and configuration."""
    service = ctx.obj['service']
    config = service.get_config()
    
    click.echo("=" * 50)
    click.echo("piADC - ADS1115 Device Status")
    click.echo("=" * 50)
    click.echo(f"I2C Address:     {config['i2c_address']}")
    click.echo(f"Gain:            {config['gain']}")
    click.echo(f"Data Rate:       {config['data_rate']} SPS")
    click.echo(f"Mode:            {config['mode']}")
    click.echo(f"Mock Mode:       {'Yes' if config['mock_mode'] else 'No'}")
    click.echo(f"Available Gains: {config['available_gains']}")
    click.echo(f"Available Rates: {config['available_data_rates']}")
    click.echo("=" * 50)


@cli.command()
@click.argument('channel', type=click.IntRange(0, 3))
@click.option('--json', 'output_json', is_flag=True, help='Output as JSON')
@click.option('--continuous', '-c', is_flag=True, help='Continuous reading')
@click.option('--interval', default=1.0, type=float, help='Interval between reads in seconds')
@click.option('--count', default=None, type=int, help='Number of readings (default: infinite)')
@click.pass_context
def read(ctx, channel, output_json, continuous, interval, count):
    """Read a single ADC channel (0-3)."""
    import time
    service = ctx.obj['service']
    
    iteration = 0
    while True:
        result = service.read_channel(channel)
        
        if output_json:
            click.echo(json.dumps(result, indent=2))
        else:
            click.echo(f"Channel {result['channel']}: {result['raw_value']} raw, {result['voltage']:.6f}V")
        
        iteration += 1
        if not continuous or (count and iteration >= count):
            break
        
        time.sleep(interval)


@cli.command()
@click.option('--json', 'output_json', is_flag=True, help='Output as JSON')
@click.option('--continuous', '-c', is_flag=True, help='Continuous reading')
@click.option('--interval', default=1.0, type=float, help='Interval between reads in seconds')
@click.option('--count', default=None, type=int, help='Number of readings (default: infinite)')
@click.pass_context
def readall(ctx, output_json, continuous, interval, count):
    """Read all 4 ADC channels."""
    import time
    service = ctx.obj['service']
    
    iteration = 0
    while True:
        result = service.read_all_channels()
        
        if output_json:
            click.echo(json.dumps(result, indent=2))
        else:
            click.echo("-" * 50)
            click.echo(f"Reading #{iteration + 1} | Mock: {result['mock_mode']} | I2C: {result['i2c_address']}")
            click.echo("-" * 50)
            for ch in result['channels']:
                click.echo(f"  Channel {ch['channel']}: {ch['raw_value']:6d} raw, {ch['voltage']:.6f}V")
        
        iteration += 1
        if not continuous or (count and iteration >= count):
            break
        
        time.sleep(interval)


@cli.command()
@click.option('--gain', type=float, help='Set gain (2/3, 1, 2, 4, 8, 16)')
@click.option('--data-rate', type=int, help='Set data rate (8, 16, 32, 64, 128, 250, 475, 860)')
@click.option('--address', help='Set I2C address (e.g., 0x48)')
@click.option('--mode', type=click.Choice(['single', 'continuous']), help='Set mode')
@click.pass_context
def config(ctx, gain, data_rate, address, mode):
    """Configure ADS1115 device settings."""
    service = ctx.obj['service']
    
    kwargs = {}
    if gain is not None:
        kwargs['gain'] = gain
    if data_rate is not None:
        kwargs['data_rate'] = data_rate
    if address is not None:
        kwargs['i2c_address'] = address
    if mode is not None:
        kwargs['mode'] = mode
    
    if not kwargs:
        click.echo("No configuration changes specified. Use --help for options.")
        return
    
    new_config = service.update_config(**kwargs)
    
    click.echo("Configuration updated:")
    click.echo(f"  I2C Address: {new_config['i2c_address']}")
    click.echo(f"  Gain:        {new_config['gain']}")
    click.echo(f"  Data Rate:   {new_config['data_rate']} SPS")
    click.echo(f"  Mode:        {new_config['mode']}")


@cli.command()
@click.pass_context
def reset(ctx):
    """Reset ADC service."""
    reset_service()
    click.echo("Service reset. Re-run any command to reinitialize.")


@cli.command()
@click.option('--output', '-o', help='Output file for logging')
@click.option('--interval', default=1.0, type=float, help='Logging interval in seconds')
@click.option('--format', 'fmt', type=click.Choice(['csv', 'json']), default='csv', help='Output format')
@click.option('--duration', default=None, type=int, help='Logging duration in seconds')
@click.pass_context
def log(ctx, output, interval, fmt, duration):
    """Log ADC readings to file."""
    import time
    import csv
    from datetime import datetime
    
    service = ctx.obj['service']
    
    if output is None:
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        output = f"ads1115_{timestamp}.{fmt}"
    
    click.echo(f"Logging to: {output}")
    click.echo(f"Interval: {interval}s")
    click.echo("Press Ctrl+C to stop...")
    
    start_time = time.time()
    
    try:
        with open(output, 'w', newline='') as f:
            if fmt == 'csv':
                writer = csv.writer(f)
                writer.writerow(['timestamp', 'channel0_raw', 'channel0_v', 'channel1_raw', 'channel1_v',
                                'channel2_raw', 'channel2_v', 'channel3_raw', 'channel3_v'])
                
                while True:
                    result = service.read_all_channels()
                    row = [datetime.now().isoformat()]
                    for ch in result['channels']:
                        row.append(ch['raw_value'])
                        row.append(ch['voltage'])
                    writer.writerow(row)
                    f.flush()
                    
                    if duration and (time.time() - start_time) >= duration:
                        break
                    time.sleep(interval)
            else:
                # JSON format - one object per line
                while True:
                    result = service.read_all_channels()
                    record = {
                        'timestamp': datetime.now().isoformat(),
                        'channels': result['channels']
                    }
                    f.write(json.dumps(record) + '\n')
                    f.flush()
                    
                    if duration and (time.time() - start_time) >= duration:
                        break
                    time.sleep(interval)
        
        click.echo(f"Logging complete. File saved: {output}")
    except KeyboardInterrupt:
        click.echo(f"\nLogging stopped. File saved: {output}")


def main():
    """Entry point for CLI."""
    cli()


if __name__ == '__main__':
    main()
