// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

import { Client, Partitioning } from 'apache-iggy';
import { log, sleep } from '../utils';
import crypto from 'crypto';


async function buildClientAndStream(connectionString: string) {
  log('Building Iggy client and connecting...');

  // Parse connection string
  const url = new URL(connectionString.replace('iggy+tcp://', 'http://'));
  const host = url.hostname;
  const port = parseInt(url.port) || 8090;
  const username = url.username || 'iggy';
  const password = url.password || 'iggy';

  const client = new Client({
    transport: 'TCP',
    options: {
      port,
      host,
      keepAlive: true,
    },
    reconnect: {
      enabled: true,
      interval: 5000,
      maxRetries: 5,
    },
    heartbeatInterval: 5000,
    credentials: { username, password },
  });

  log('Creating stream and topic...');
  const streamName = `stream-${crypto.randomBytes(4).toString('hex')}`;
  const topicName = `topic-${crypto.randomBytes(4).toString('hex')}`;

  const stream = await client.stream.create({
    name: streamName,
  });

  const topic = await client.topic.create({
    streamId: stream.id,
    name: topicName,
    partitionCount: 1,
    compressionAlgorithm: 1,
  });

  log(`Stream created: ${stream.id}`);
  log(`Topic created: ${topic.id}`);

  return { client, stream, topic };
}

async function produceAndConsume(client: Client, stream: any, topic: any) {
  log('Starting producer and consumer...');

  log('Sending 3 test messages...');
  const messages = [
    { payload: 'Hello World' },
    { payload: 'Hola Iggy' },
    { payload: 'Hi Apache' },
  ];

  await client.message.send({
    streamId: stream.id,
    topicId: topic.id,
    messages,
    partition: Partitioning.PartitionId(topic.partitions[0].id),
  });

  log('Messages sent, waiting for consumption...');
  await sleep(500);

  log('Polling messages...');
  const polledMessages = await client.message.poll({
    streamId: stream.id,
    topicId: topic.id,
    consumer: { kind: 1, id: 1 }, // Consumer.Single
    partitionId: topic.partitions[0].id,
    pollingStrategy: { kind: 1, value: 0n }, // Offset(0)
    count: 10,
    autocommit: false,
  });

  if (polledMessages && polledMessages.messages.length > 0) {
    log(`Consumed ${polledMessages.messages.length} messages:`);
    for (const message of polledMessages.messages) {
      const payload = new TextDecoder().decode(new Uint8Array(Object.values(message.payload)));
      log(`  - ${payload}`);
    }
  }
}

async function cleanup(client: Client, stream: any, topic: any) {
  log('Cleaning up...');
  try {
    await client.topic.delete({
      streamId: stream.id,
      topicId: topic.id,
      partitionsCount: 1,
    });
    log('Topic deleted');
  } catch (error) {
    log(`Error deleting topic: ${error}`);
  }

  try {
    await client.stream.delete({ streamId: stream.id });
    log('Stream deleted');
  } catch (error) {
    log(`Error deleting stream: ${error}`);
  }
}

async function main() {
  const connectionString = process.argv[2] || 'iggy+tcp://iggy:iggy@127.0.0.1:8090';

  try {
    log('Stream Builder Example');
    const { client, stream, topic } = await buildClientAndStream(connectionString);

    await produceAndConsume(client, stream, topic);

    await cleanup(client, stream, topic);

    await client.destroy();
    log('Disconnected from server');
  } catch (error) {
    log(`Error: ${error}`);
    process.exitCode = 1;
  }
}

await main();
