package main

import (
	"bufio"
	"fmt"
	"log"
	"net/http"
	"os"
	"sync"
)

func main() {
	// Check if the correct number of arguments is passed
	if len(os.Args) < 2 {
		fmt.Println("Usage: go run main.go <input_file>")
		return
	}

	// Get the input file from command line arguments
	inputFile := os.Args[1]

	// Open the input file
	file, err := os.Open(inputFile)
	if err != nil {
		log.Fatalf("Failed to open file: %v\n", err)
	}
	defer file.Close()

	// Create output files for works and failed URLs
	worksFile, err := os.Create("works.txt")
	if err != nil {
		log.Fatalf("Failed to create works.txt: %v\n", err)
	}
	defer worksFile.Close()

	failedFile, err := os.Create("failed.txt")
	if err != nil {
		log.Fatalf("Failed to create failed.txt: %v\n", err)
	}
	defer failedFile.Close()

	// Create a scanner to read the input file line by line
	scanner := bufio.NewScanner(file)

	// Channels for results
	worksChan := make(chan string)
	failedChan := make(chan string)

	// WaitGroup to wait for all goroutines to finish
	var wg sync.WaitGroup

	// Worker function to check URL
	checkURL := func(url string) {
		defer wg.Done() // Decrease the counter when the goroutine completes

		// Check if the URL is accessible
		resp, err := http.Get(url)
		if err != nil || resp.StatusCode != http.StatusOK {
			// If there's an error or the status is not 200 OK, send to failed channel
			failedChan <- url
		} else {
			// If the URL is successful, send to works channel
			worksChan <- url
		}

		// Close the response body if the request was successful
		if resp != nil {
			resp.Body.Close()
		}
	}

	// Goroutine to handle writing to works.txt
	go func() {
		for url := range worksChan {
			worksFile.WriteString(url + "\n")
		}
	}()

	// Goroutine to handle writing to failed.txt
	go func() {
		for url := range failedChan {
			failedFile.WriteString(url + "\n")
		}
	}()

	// Iterate through each line (URL) in the file and start a goroutine for each
	for scanner.Scan() {
		url := scanner.Text()
		wg.Add(1) // Increase the counter for each goroutine
		go checkURL(url)
	}

	// Wait for all goroutines to finish
	wg.Wait()

	// Close the channels once all URLs have been processed
	close(worksChan)
	close(failedChan)

	// Check for any scanner errors
	if err := scanner.Err(); err != nil {
		log.Fatalf("Error reading file: %v\n", err)
	}

	fmt.Println("URL check completed. See works.txt and failed.txt for results.")
}