#!/usr/bin/env node
/**
 * Seed Test Projects for Localhost Testing
 * 
 * Creates test project data for localhost API server testing.
 * Can be run standalone or integrated into your local dev server.
 * 
 * @author Matthew Raymer
 * @version 1.0.0
 */

const http = require('http');

/**
 * Generate a valid ULID (26 characters, Crockford base32)
 * Simplified version for testing - not cryptographically secure
 */
function generateULID() {
  const timestamp = Date.now();
  // Crockford base32 alphabet (0-9, A-Z excluding I, L, O, U)
  const alphabet = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
  const timestampPart = timestamp.toString(36).toUpperCase().padStart(10, '0');
  const randomPart = Array.from({ length: 16 }, () => 
    alphabet[Math.floor(Math.random() * alphabet.length)]
  ).join('');
  return (timestampPart + randomPart).substring(0, 26);
}

/**
 * Generate a valid plan handle ID in URI format
 * Default format: https://endorser.ch/entity/{ULID}
 */
function generateValidPlanHandleId() {
  return `https://endorser.ch/entity/${generateULID()}`;
}

/**
 * Generate a test JWT ID with timestamp prefix for sorting
 */
function generateJwtId(timestamp = Date.now()) {
  const random = Math.random().toString(36).substring(2, 8);
  const hash = Math.random().toString(36).substring(2, 10);
  return `${Math.floor(timestamp / 1000)}_${random}_${hash}`;
}

/**
 * Generate test project data
 */
function generateTestProject(handleId, index = 0) {
  const now = Date.now();
  const startTime = new Date(now + (index * 86400000)); // 1 day apart
  const endTime = new Date(startTime.getTime() + (30 * 86400000)); // 30 days later

  return {
    jwtId: generateJwtId(now + (index * 1000)),
    handleId: handleId,
    name: `Test Project ${index + 1}`,
    description: `This is test project ${index + 1} for localhost prefetch testing. Created for User Zero starred plans querying.`,
    issuerDid: "did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F",
    agentDid: "did:test:agent_" + index,
    startTime: startTime.toISOString(),
    endTime: endTime.toISOString(),
    locLat: 40.7128 + (index * 0.1), // Vary location slightly
    locLon: -74.0060 + (index * 0.1),
    url: `https://test-project-${index + 1}.timesafari.test`,
    version: "1.0.0"
  };
}

/**
 * Generate complete test project with previous claim
 */
function generateTestProjectWithClaim(handleId, index = 0) {
  const project = generateTestProject(handleId, index);
  const previousClaimJwtId = generateJwtId(Date.now() - (86400000 * 2)); // 2 days ago

  return {
    planSummary: project,
    previousClaim: {
      jwtId: previousClaimJwtId,
      claimType: "project_update",
      claimData: {
        message: `Previous update for ${handleId}`,
        version: "0.9.0"
      },
      metadata: {
        createdAt: new Date(Date.now() - (86400000 * 2)).toISOString(),
        updatedAt: new Date(Date.now() - (86400000)).toISOString()
      }
    }
  };
}

/**
 * Default test project IDs from config
 * 
 * Plan handle IDs must be valid URIs (RFC 3986 format):
 * - Default format: https://endorser.ch/entity/{26-char-ULID}
 * - ULID is 26 characters, Crockford base32 encoded
 * - Any valid URI scheme is accepted: http://, https://, did:, etc.
 * 
 * For real testing, use actual plan handle IDs from your TimeSafari database.
 * To get valid IDs:
 * 1. Create projects in TimeSafari app and note handleId from API responses
 * 2. Query your local database: SELECT handleId FROM plans LIMIT 5
 * 3. Check starred projects: settings.starredPlanHandleIds
 * 
 * The IDs below are auto-generated valid URIs for testing structure only.
 * Replace with real IDs from your database for actual prefetch testing.
 */
const DEFAULT_TEST_PROJECT_IDS = [
  // Auto-generate valid format IDs for testing
  generateValidPlanHandleId(),
  generateValidPlanHandleId(),
  generateValidPlanHandleId(),
  generateValidPlanHandleId(),
  generateValidPlanHandleId()
];

/**
 * Generate all test projects
 */
function generateAllTestProjects(projectIds = DEFAULT_TEST_PROJECT_IDS) {
  return projectIds.map((handleId, index) =>
    generateTestProjectWithClaim(handleId, index)
  );
}

/**
 * Seed projects to localhost API server
 * 
 * **IMPORTANT**: The TimeSafari API creates plans via POST `/api/v2/claim` with PlanAction JWTs.
 * This function attempts to POST to `/api/test/seed-projects` if your API has a custom test seed endpoint.
 * 
 * For real TimeSafari APIs:
 * 1. Create plans via the TimeSafari app UI (recommended)
 * 2. Import PlanAction JWTs via POST `/api/v2/claim` (requires DID signing)
 * 3. Use direct database inserts (not recommended)
 * 
 * This seed function is primarily for custom test endpoints or the test-api-server-with-seed.js
 */
function seedToLocalhost(apiUrl, projectIds = DEFAULT_TEST_PROJECT_IDS) {
  return new Promise((resolve, reject) => {
    const projects = generateAllTestProjects(projectIds);
    
    console.log(`📦 Generating ${projects.length} test projects...`);
    projects.forEach((project, index) => {
      console.log(`  ${index + 1}. ${project.planSummary.handleId} - ${project.planSummary.name}`);
    });

    console.log('');
    console.log('⚠️  NOTE: This attempts to POST to /api/test/seed-projects');
    console.log('   If your API doesn\'t have this endpoint, create plans via:');
    console.log('   1. TimeSafari App UI (easiest)');
    console.log('   2. POST /api/v2/claim with PlanAction JWT (requires DID signing)');
    console.log('   3. Direct database inserts');
    console.log('');

    // If your API has a seed endpoint, use this:
    const seedUrl = `${apiUrl}/api/test/seed-projects`;
    const postData = JSON.stringify({ projects });

    const options = {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Content-Length': Buffer.byteLength(postData)
      }
    };

    const req = http.request(seedUrl, options, (res) => {
      let data = '';

      res.on('data', (chunk) => {
        data += chunk;
      });

      res.on('end', () => {
        if (res.statusCode === 200 || res.statusCode === 201) {
          console.log('✅ Test projects seeded successfully');
          console.log(`📊 Response: ${data}`);
          resolve(JSON.parse(data));
        } else {
          console.error(`❌ Seed failed: ${res.statusCode} ${res.statusMessage}`);
          console.error(`Response: ${data}`);
          reject(new Error(`HTTP ${res.statusCode}: ${data}`));
        }
      });
    });

    req.on('error', (error) => {
      console.error(`❌ Request error: ${error.message}`);
      reject(error);
    });

    req.write(postData);
    req.end();
  });
}

/**
 * Generate mock API server response data
 * 
 * Returns the data structure that your localhost API should return
 */
function getMockApiResponse(projectIds = DEFAULT_TEST_PROJECT_IDS, afterId = null) {
  const allProjects = generateAllTestProjects(projectIds);
  
  // Filter by afterId if provided (simple comparison by jwtId)
  let filteredProjects = allProjects;
  if (afterId) {
    const afterIndex = allProjects.findIndex(p => p.planSummary.jwtId === afterId);
    if (afterIndex >= 0) {
      filteredProjects = allProjects.slice(afterIndex + 1);
    } else {
      // If afterId not found, return all (for testing)
      filteredProjects = allProjects;
    }
  }

  const nextAfterId = filteredProjects.length > 0
    ? filteredProjects[filteredProjects.length - 1].planSummary.jwtId
    : null;

  return {
    data: filteredProjects,
    hitLimit: false,
    pagination: {
      hasMore: false,
      nextAfterId: nextAfterId
    }
  };
}

/**
 * Export project data as JSON file
 */
function exportToJSON(filename = 'test-projects.json', projectIds = DEFAULT_TEST_PROJECT_IDS) {
  const fs = require('fs');
  const projects = generateAllTestProjects(projectIds);
  const data = {
    projects: projects,
    generatedAt: new Date().toISOString(),
    count: projects.length
  };

  fs.writeFileSync(filename, JSON.stringify(data, null, 2));
  console.log(`💾 Exported ${projects.length} test projects to ${filename}`);
  return data;
}

// CLI usage
if (require.main === module) {
  const args = process.argv.slice(2);
  const command = args[0];

  switch (command) {
    case 'export':
      {
        const filename = args[1] || 'test-projects.json';
        const projectIds = args[2] ? args[2].split(',') : DEFAULT_TEST_PROJECT_IDS;
        
        // Warn if using auto-generated IDs (they'll be valid URIs but not from real database)
        console.log('📝 Using provided plan handle IDs.');
        console.log('   Note: For real testing, use IDs from your TimeSafari database.');
        console.log('   Valid format: https://endorser.ch/entity/{ULID} or any valid URI');
        console.log('');
        
        exportToJSON(filename, projectIds);
      }
      break;

    case 'seed':
      {
        const apiUrl = args[1] || 'http://localhost:3000';
        const projectIds = args[2] ? args[2].split(',') : DEFAULT_TEST_PROJECT_IDS;
        
        // Validate plan IDs are valid URIs (RFC 3986)
        const invalidIds = projectIds.filter(id => !id.match(/^[A-Za-z][A-Za-z0-9+.-]+:/));
        if (invalidIds.length > 0) {
          console.error('❌ ERROR: Invalid plan handle ID format.');
          console.error('   Plan handle IDs must be valid URIs (RFC 3986).');
          console.error('   Format: https://endorser.ch/entity/{ULID}');
          console.error('   Example: https://endorser.ch/entity/01GQBE7Q0RQQAGJMEEW6RSGKTF');
          console.error(`   Invalid IDs: ${invalidIds.join(', ')}`);
          console.error('');
          console.error('   Usage: node scripts/seed-test-projects.js seed <apiUrl> "<uri1>,<uri2>,<uri3>"');
          process.exit(1);
        }
        
        seedToLocalhost(apiUrl, projectIds)
          .then(() => {
            console.log('✅ Seeding complete');
            process.exit(0);
          })
          .catch((error) => {
            console.error('❌ Seeding failed:', error.message);
            process.exit(1);
          });
      }
      break;

    case 'generate':
    default:
      {
        const projectIds = args[1] ? args[1].split(',') : DEFAULT_TEST_PROJECT_IDS;
        
        console.log('📝 Generated test projects with valid URI format handle IDs.');
        console.log('   Format: https://endorser.ch/entity/{ULID}');
        console.log('   For real testing, replace with IDs from your TimeSafari database.');
        
        const projects = generateAllTestProjects(projectIds);
        console.log(JSON.stringify({ data: projects }, null, 2));
      }
      break;
  }
}

module.exports = {
  generateTestProject,
  generateTestProjectWithClaim,
  generateAllTestProjects,
  getMockApiResponse,
  seedToLocalhost,
  exportToJSON,
  DEFAULT_TEST_PROJECT_IDS,
  generateJwtId
};

