const https = require('https');

/**
 * Fetch holiday data from timor.tech API for a specific year
 * @param {number} year 
 * @returns {Promise<object>}
 */
function fetchHolidaysFromNetwork(year) {
  return new Promise((resolve, reject) => {
    // Note: timor.tech API works best with trailing slash
    const url = `https://timor.tech/api/holiday/year/${year}/`;
    https.get(url, { headers: { 'User-Agent': 'WorkTime-Manager/1.0' } }, (res) => {
      let rawData = '';
      res.on('data', (chunk) => { rawData += chunk; });
      res.on('end', () => {
        try {
          const parsed = JSON.parse(rawData);
          if (parsed.code === 0 && parsed.holiday) {
            resolve(parsed.holiday);
          } else {
            reject(new Error(`API returned code ${parsed.code}`));
          }
        } catch (e) {
          reject(e);
        }
      });
    }).on('error', (err) => {
      reject(err);
    });
  });
}

/**
 * Get holiday data for a specific year, from cache or network
 * @param {object} db DB wrapper instance
 * @param {number} year 
 * @returns {Promise<object|null>}
 */
async function getHolidays(db, year) {
  try {
    const cached = db.get('SELECT holiday_data FROM holiday_cache WHERE year = ?', [year]);
    if (cached) {
      return JSON.parse(cached.holiday_data);
    }
    
    // Not cached, fetch from network
    console.log(`[Holiday] Fetching holiday data from network for year ${year}...`);
    const holidays = await fetchHolidaysFromNetwork(year);
    
    // Save to cache
    db.run(
      'INSERT OR REPLACE INTO holiday_cache (year, holiday_data, updated_at) VALUES (?, ?, datetime(\'now\', \'localtime\'))',
      [year, JSON.stringify(holidays)]
    );
    return holidays;
  } catch (e) {
    console.error(`[Holiday] Error getting holidays for ${year}:`, e.message);
    return null;
  }
}

/**
 * Helper to check if a date is weekend (Sat/Sun) in local time
 * @param {string} dateStr YYYY-MM-DD
 * @returns {boolean}
 */
function isWeekendDefault(dateStr) {
  const d = new Date(dateStr + 'T00:00:00');
  const day = d.getDay();
  return day === 0 || day === 6;
}

/**
 * Calculate the number of workdays for each month in a given year
 * @param {number} year 
 * @param {object|null} holidayMap 
 * @returns {Array<{month: number, days: number}>}
 */
function calculateMonthlyWorkdays(year, holidayMap) {
  const result = [];
  for (let m = 1; m <= 12; m++) {
    const daysInMonth = new Date(year, m, 0).getDate();
    let workdays = 0;
    
    for (let day = 1; day <= daysInMonth; day++) {
      const dStr = `${year}-${String(m).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
      const mmDd = `${String(m).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
      
      let isWork = true;
      if (holidayMap && holidayMap[mmDd]) {
        // If date is in the map, holiday === true means rest day, holiday === false means work day (調休补班)
        isWork = !holidayMap[mmDd].holiday;
      } else {
        // Fall back to default weekends
        isWork = !isWeekendDefault(dStr);
      }
      
      if (isWork) {
        workdays++;
      }
    }
    result.push({ month: m, days: workdays });
  }
  return result;
}

/**
 * Sync holiday data from network, calculate and update database workdays
 * @param {object} db 
 * @param {number} year 
 * @returns {Promise<Array<{month: number, days: number}>>}
 */
async function syncYearWorkdays(db, year) {
  // Clear cache first to force fresh fetch on manual sync request
  db.run('DELETE FROM holiday_cache WHERE year = ?', [year]);
  
  const holidayMap = await getHolidays(db, year);
  if (!holidayMap) {
    throw new Error('无法从网络同步节假日数据，请检查网络连接');
  }
  
  const monthlyWorkdays = calculateMonthlyWorkdays(year, holidayMap);
  
  // Save to workdays table
  for (const item of monthlyWorkdays) {
    const existing = db.get('SELECT id FROM workdays WHERE year = ? AND month = ?', [year, item.month]);
    if (existing) {
      db.run('UPDATE workdays SET days = ? WHERE year = ? AND month = ?', [item.days, year, item.month]);
    } else {
      db.run('INSERT INTO workdays (year, month, days) VALUES (?, ?, ?)', [year, item.month, item.days]);
    }
  }
  
  return monthlyWorkdays;
}

module.exports = {
  getHolidays,
  syncYearWorkdays,
  calculateMonthlyWorkdays
};
